From 964e5b39e41b15813a3eee96200edd916db51ea6 Mon Sep 17 00:00:00 2001 From: Antwy <38584695+Antwy@users.noreply.github.com> Date: Wed, 28 Feb 2024 19:58:32 +0300 Subject: [PATCH] RISCV basic support --- Dockerfile | 3 +- src/libtriton/CMakeLists.txt | 10 + src/libtriton/arch/architecture.cpp | 9 + src/libtriton/arch/irBuilder.cpp | 10 +- src/libtriton/arch/riscv/riscv32Cpu.cpp | 741 +++++ src/libtriton/arch/riscv/riscv64Cpu.cpp | 741 +++++ src/libtriton/arch/riscv/riscvSemantics.cpp | 2650 +++++++++++++++++ .../arch/riscv/riscvSpecifications.cpp | 1233 ++++++++ .../python/namespaces/initArchNamespace.cpp | 4 + src/libtriton/includes/triton/archEnums.hpp | 62 + .../includes/triton/externalLibs.hpp | 1 + src/libtriton/includes/triton/irBuilder.hpp | 3 + src/libtriton/includes/triton/riscv32.spec | 89 + src/libtriton/includes/triton/riscv32Cpu.hpp | 284 ++ src/libtriton/includes/triton/riscv64.spec | 89 + src/libtriton/includes/triton/riscv64Cpu.hpp | 284 ++ .../includes/triton/riscvSemantics.hpp | 388 +++ .../includes/triton/riscvSpecifications.hpp | 365 +++ .../includes/triton/shortcutRegister.hpp | 38 + src/scripts/docker/Dockerfile | 2 +- src/testers/CMakeLists.txt | 4 + src/testers/riscv/unicorn_test_riscv32.py | 614 ++++ src/testers/riscv/unicorn_test_riscv64.py | 667 +++++ 23 files changed, 8288 insertions(+), 3 deletions(-) create mode 100644 src/libtriton/arch/riscv/riscv32Cpu.cpp create mode 100644 src/libtriton/arch/riscv/riscv64Cpu.cpp create mode 100644 src/libtriton/arch/riscv/riscvSemantics.cpp create mode 100644 src/libtriton/arch/riscv/riscvSpecifications.cpp create mode 100644 src/libtriton/includes/triton/riscv32.spec create mode 100644 src/libtriton/includes/triton/riscv32Cpu.hpp create mode 100644 src/libtriton/includes/triton/riscv64.spec create mode 100644 src/libtriton/includes/triton/riscv64Cpu.hpp create mode 100644 src/libtriton/includes/triton/riscvSemantics.hpp create mode 100644 src/libtriton/includes/triton/riscvSpecifications.hpp create mode 100644 src/testers/riscv/unicorn_test_riscv32.py create mode 100644 src/testers/riscv/unicorn_test_riscv64.py diff --git a/Dockerfile b/Dockerfile index db119f18b..ce42507ca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,8 @@ RUN apt update && apt upgrade -y && apt install -y build-essential clang curl gi # libcapstone >= 4.0.x RUN cd /tmp && \ curl -o cap.tgz -L https://github.com/aquynh/capstone/archive/4.0.2.tar.gz && \ - tar xvf cap.tgz && cd capstone-4.0.2/ && ./make.sh && make install && rm -rf /tmp/cap* \ + tar xvf cap.tgz && cd capstone-4.0.2/ && CAPSTONE_ARCHS="arm aarch64 riscv x86" ./make.sh && \ + make install && rm -rf /tmp/cap* \ && ln -s /usr/lib/libcapstone.so.4 /usr/lib/x86_64-linux-gnu/libcapstone.so # libbitwuzla >= 0.4.0 diff --git a/src/libtriton/CMakeLists.txt b/src/libtriton/CMakeLists.txt index 44d7f66d3..7379ddf16 100644 --- a/src/libtriton/CMakeLists.txt +++ b/src/libtriton/CMakeLists.txt @@ -32,6 +32,10 @@ set(LIBTRITON_SOURCE_FILES arch/memoryAccess.cpp arch/operandWrapper.cpp arch/register.cpp + arch/riscv/riscv32Cpu.cpp + arch/riscv/riscv64Cpu.cpp + arch/riscv/riscvSemantics.cpp + arch/riscv/riscvSpecifications.cpp arch/x86/x8664Cpu.cpp arch/x86/x86Cpu.cpp arch/x86/x86Semantics.cpp @@ -118,6 +122,12 @@ set(LIBTRITON_HEADER_FILES includes/triton/pathConstraint.hpp includes/triton/pathManager.hpp includes/triton/register.hpp + includes/triton/riscv32.spec + includes/triton/riscv64.spec + includes/triton/riscv32Cpu.hpp + includes/triton/riscv64Cpu.hpp + includes/triton/riscvSemantics.hpp + includes/triton/riscvSpecifications.hpp includes/triton/semanticsInterface.hpp includes/triton/shortcutRegister.hpp includes/triton/solverEngine.hpp diff --git a/src/libtriton/arch/architecture.cpp b/src/libtriton/arch/architecture.cpp index d94e5f2b8..d8ed8ddd0 100644 --- a/src/libtriton/arch/architecture.cpp +++ b/src/libtriton/arch/architecture.cpp @@ -16,6 +16,9 @@ #include #include #include +#include +#include +#include @@ -54,6 +57,8 @@ namespace triton { case triton::arch::ARCH_X86: this->cpu.reset(new(std::nothrow) triton::arch::x86::x86Cpu(this->callbacks)); break; case triton::arch::ARCH_AARCH64: this->cpu.reset(new(std::nothrow) triton::arch::arm::aarch64::AArch64Cpu(this->callbacks)); break; case triton::arch::ARCH_ARM32: this->cpu.reset(new(std::nothrow) triton::arch::arm::arm32::Arm32Cpu(this->callbacks)); break; + case triton::arch::ARCH_RV64: this->cpu.reset(new(std::nothrow) triton::arch::riscv::riscv64Cpu(this->callbacks)); break; + case triton::arch::ARCH_RV32: this->cpu.reset(new(std::nothrow) triton::arch::riscv::riscv32Cpu(this->callbacks)); break; default: throw triton::exceptions::Architecture("Architecture::setArchitecture(): Architecture not supported."); } @@ -400,6 +405,10 @@ namespace triton { case triton::arch::ARCH_X86_64: return triton::arch::x86::nop; + case triton::arch::ARCH_RV64: + case triton::arch::ARCH_RV32: + return triton::arch::riscv::nop; + default: throw triton::exceptions::Architecture("Architecture::getNopInstruction(): Invalid architecture."); } diff --git a/src/libtriton/arch/irBuilder.cpp b/src/libtriton/arch/irBuilder.cpp index 771026397..2273f4939 100644 --- a/src/libtriton/arch/irBuilder.cpp +++ b/src/libtriton/arch/irBuilder.cpp @@ -16,6 +16,7 @@ #include #include #include +#include @@ -44,8 +45,9 @@ namespace triton { this->aarch64Isa = new(std::nothrow) triton::arch::arm::aarch64::AArch64Semantics(architecture, symbolicEngine, taintEngine, astCtxt); this->arm32Isa = new(std::nothrow) triton::arch::arm::arm32::Arm32Semantics(architecture, symbolicEngine, taintEngine, astCtxt); this->x86Isa = new(std::nothrow) triton::arch::x86::x86Semantics(architecture, symbolicEngine, taintEngine, modes, astCtxt); + this->riscvIsa = new(std::nothrow) triton::arch::riscv::riscvSemantics(architecture, symbolicEngine, taintEngine, modes, astCtxt); - if (this->x86Isa == nullptr || this->aarch64Isa == nullptr || this->arm32Isa == nullptr) + if (this->x86Isa == nullptr || this->aarch64Isa == nullptr || this->arm32Isa == nullptr || this->riscvIsa == nullptr) throw triton::exceptions::IrBuilder("IrBuilder::IrBuilder(): Not enough memory."); } @@ -54,6 +56,7 @@ namespace triton { delete this->aarch64Isa; delete this->arm32Isa; delete this->x86Isa; + delete this->riscvIsa; } @@ -89,6 +92,11 @@ namespace triton { ret = this->x86Isa->buildSemantics(inst); break; + case triton::arch::ARCH_RV64: + case triton::arch::ARCH_RV32: + ret = this->riscvIsa->buildSemantics(inst); + break; + default: throw triton::exceptions::IrBuilder("IrBuilder::buildSemantics(): Architecture not supported."); break; diff --git a/src/libtriton/arch/riscv/riscv32Cpu.cpp b/src/libtriton/arch/riscv/riscv32Cpu.cpp new file mode 100644 index 000000000..54ebf5b95 --- /dev/null +++ b/src/libtriton/arch/riscv/riscv32Cpu.cpp @@ -0,0 +1,741 @@ +//! \file +/* +** Copyright (C) - Triton +** +** This program is under the terms of the Apache License 2.0. +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + + +namespace triton { + namespace arch { + namespace riscv { + + riscv32Cpu::riscv32Cpu(triton::callbacks::Callbacks* callbacks) : riscvSpecifications(ARCH_RV32) { + this->callbacks = callbacks; + this->handle = 0; + + this->clear(); + this->disassInit(); + } + + + riscv32Cpu::riscv32Cpu(const riscv32Cpu& other) : riscvSpecifications(ARCH_RV32) { + this->copy(other); + } + + + riscv32Cpu::~riscv32Cpu() { + this->memory.clear(); + if (this->handle) { + triton::extlibs::capstone::cs_close(&this->handle); + } + } + + void riscv32Cpu::disassInit(void) { + if (this->handle) { + triton::extlibs::capstone::cs_close(&this->handle); + } + + // CS_MODE_RISCV32 | CS_MODE_RISCVC + auto rv_mode = static_cast((1 << 0) | (1 << 2)); + if (triton::extlibs::capstone::cs_open(triton::extlibs::capstone::CS_ARCH_RISCV, rv_mode, &this->handle) != triton::extlibs::capstone::CS_ERR_OK) + throw triton::exceptions::Disassembly("riscv32Cpu::disassInit(): Cannot open capstone."); + + triton::extlibs::capstone::cs_option(this->handle, triton::extlibs::capstone::CS_OPT_DETAIL, triton::extlibs::capstone::CS_OPT_ON); + } + + + void riscv32Cpu::copy(const riscv32Cpu& other) { + this->callbacks = other.callbacks; + this->memory = other.memory; + + std::memcpy(this->x0, other.x0, sizeof(this->x0)); + std::memcpy(this->x1, other.x1, sizeof(this->x1)); + std::memcpy(this->sp, other.sp, sizeof(this->sp)); + std::memcpy(this->x3, other.x3, sizeof(this->x3)); + std::memcpy(this->x4, other.x4, sizeof(this->x4)); + std::memcpy(this->x5, other.x5, sizeof(this->x5)); + std::memcpy(this->x6, other.x6, sizeof(this->x6)); + std::memcpy(this->x7, other.x7, sizeof(this->x7)); + std::memcpy(this->x8, other.x8, sizeof(this->x8)); + std::memcpy(this->x9, other.x9, sizeof(this->x9)); + std::memcpy(this->x10, other.x10, sizeof(this->x10)); + std::memcpy(this->x11, other.x11, sizeof(this->x11)); + std::memcpy(this->x12, other.x12, sizeof(this->x12)); + std::memcpy(this->x13, other.x13, sizeof(this->x13)); + std::memcpy(this->x14, other.x14, sizeof(this->x14)); + std::memcpy(this->x15, other.x15, sizeof(this->x15)); + std::memcpy(this->x16, other.x16, sizeof(this->x16)); + std::memcpy(this->x17, other.x17, sizeof(this->x17)); + std::memcpy(this->x18, other.x18, sizeof(this->x18)); + std::memcpy(this->x19, other.x19, sizeof(this->x19)); + std::memcpy(this->x20, other.x20, sizeof(this->x20)); + std::memcpy(this->x21, other.x21, sizeof(this->x21)); + std::memcpy(this->x22, other.x22, sizeof(this->x22)); + std::memcpy(this->x23, other.x23, sizeof(this->x23)); + std::memcpy(this->x24, other.x24, sizeof(this->x24)); + std::memcpy(this->x25, other.x25, sizeof(this->x25)); + std::memcpy(this->x26, other.x26, sizeof(this->x26)); + std::memcpy(this->x27, other.x27, sizeof(this->x27)); + std::memcpy(this->x28, other.x28, sizeof(this->x28)); + std::memcpy(this->x29, other.x29, sizeof(this->x29)); + std::memcpy(this->x30, other.x30, sizeof(this->x30)); + std::memcpy(this->x31, other.x31, sizeof(this->x31)); + std::memcpy(this->pc, other.pc, sizeof(this->pc)); + std::memcpy(this->f0, other.f0, sizeof(this->f0)); + std::memcpy(this->f1, other.f1, sizeof(this->f1)); + std::memcpy(this->f2, other.f2, sizeof(this->f2)); + std::memcpy(this->f3, other.f3, sizeof(this->f3)); + std::memcpy(this->f4, other.f4, sizeof(this->f4)); + std::memcpy(this->f5, other.f5, sizeof(this->f5)); + std::memcpy(this->f6, other.f6, sizeof(this->f6)); + std::memcpy(this->f7, other.f7, sizeof(this->f7)); + std::memcpy(this->f8, other.f8, sizeof(this->f8)); + std::memcpy(this->f9, other.f9, sizeof(this->f9)); + std::memcpy(this->f10, other.f10, sizeof(this->f10)); + std::memcpy(this->f11, other.f11, sizeof(this->f11)); + std::memcpy(this->f12, other.f12, sizeof(this->f12)); + std::memcpy(this->f13, other.f13, sizeof(this->f13)); + std::memcpy(this->f14, other.f14, sizeof(this->f14)); + std::memcpy(this->f15, other.f15, sizeof(this->f15)); + std::memcpy(this->f16, other.f16, sizeof(this->f16)); + std::memcpy(this->f17, other.f17, sizeof(this->f17)); + std::memcpy(this->f18, other.f18, sizeof(this->f18)); + std::memcpy(this->f19, other.f19, sizeof(this->f19)); + std::memcpy(this->f20, other.f20, sizeof(this->f20)); + std::memcpy(this->f21, other.f21, sizeof(this->f21)); + std::memcpy(this->f22, other.f22, sizeof(this->f22)); + std::memcpy(this->f23, other.f23, sizeof(this->f23)); + std::memcpy(this->f24, other.f24, sizeof(this->f24)); + std::memcpy(this->f25, other.f25, sizeof(this->f25)); + std::memcpy(this->f26, other.f26, sizeof(this->f26)); + std::memcpy(this->f27, other.f27, sizeof(this->f27)); + std::memcpy(this->f28, other.f28, sizeof(this->f28)); + std::memcpy(this->f29, other.f29, sizeof(this->f29)); + std::memcpy(this->f30, other.f30, sizeof(this->f30)); + std::memcpy(this->f31, other.f31, sizeof(this->f31)); + } + + + void riscv32Cpu::clear(void) { + /* Clear memory */ + this->memory.clear(); + + /* Clear registers */ + std::memset(this->x0, 0x00, sizeof(this->x0)); + std::memset(this->x1, 0x00, sizeof(this->x1)); + std::memset(this->sp, 0x00, sizeof(this->sp)); + std::memset(this->x3, 0x00, sizeof(this->x3)); + std::memset(this->x4, 0x00, sizeof(this->x4)); + std::memset(this->x5, 0x00, sizeof(this->x5)); + std::memset(this->x6, 0x00, sizeof(this->x6)); + std::memset(this->x7, 0x00, sizeof(this->x7)); + std::memset(this->x8, 0x00, sizeof(this->x8)); + std::memset(this->x9, 0x00, sizeof(this->x9)); + std::memset(this->x10, 0x00, sizeof(this->x10)); + std::memset(this->x11, 0x00, sizeof(this->x11)); + std::memset(this->x12, 0x00, sizeof(this->x12)); + std::memset(this->x13, 0x00, sizeof(this->x13)); + std::memset(this->x14, 0x00, sizeof(this->x14)); + std::memset(this->x15, 0x00, sizeof(this->x15)); + std::memset(this->x16, 0x00, sizeof(this->x16)); + std::memset(this->x17, 0x00, sizeof(this->x17)); + std::memset(this->x18, 0x00, sizeof(this->x18)); + std::memset(this->x19, 0x00, sizeof(this->x19)); + std::memset(this->x20, 0x00, sizeof(this->x20)); + std::memset(this->x21, 0x00, sizeof(this->x21)); + std::memset(this->x22, 0x00, sizeof(this->x22)); + std::memset(this->x23, 0x00, sizeof(this->x23)); + std::memset(this->x24, 0x00, sizeof(this->x24)); + std::memset(this->x25, 0x00, sizeof(this->x25)); + std::memset(this->x26, 0x00, sizeof(this->x26)); + std::memset(this->x27, 0x00, sizeof(this->x27)); + std::memset(this->x28, 0x00, sizeof(this->x28)); + std::memset(this->x29, 0x00, sizeof(this->x29)); + std::memset(this->x30, 0x00, sizeof(this->x30)); + std::memset(this->x31, 0x00, sizeof(this->x31)); + std::memset(this->pc, 0x00, sizeof(this->pc)); + std::memset(this->f0, 0x00, sizeof(this->f0)); + std::memset(this->f1, 0x00, sizeof(this->f1)); + std::memset(this->f2, 0x00, sizeof(this->f2)); + std::memset(this->f3, 0x00, sizeof(this->f3)); + std::memset(this->f4, 0x00, sizeof(this->f4)); + std::memset(this->f5, 0x00, sizeof(this->f5)); + std::memset(this->f6, 0x00, sizeof(this->f6)); + std::memset(this->f7, 0x00, sizeof(this->f7)); + std::memset(this->f8, 0x00, sizeof(this->f8)); + std::memset(this->f9, 0x00, sizeof(this->f9)); + std::memset(this->f10, 0x00, sizeof(this->f10)); + std::memset(this->f11, 0x00, sizeof(this->f11)); + std::memset(this->f12, 0x00, sizeof(this->f12)); + std::memset(this->f13, 0x00, sizeof(this->f13)); + std::memset(this->f14, 0x00, sizeof(this->f14)); + std::memset(this->f15, 0x00, sizeof(this->f15)); + std::memset(this->f16, 0x00, sizeof(this->f16)); + std::memset(this->f17, 0x00, sizeof(this->f17)); + std::memset(this->f18, 0x00, sizeof(this->f18)); + std::memset(this->f19, 0x00, sizeof(this->f19)); + std::memset(this->f20, 0x00, sizeof(this->f20)); + std::memset(this->f21, 0x00, sizeof(this->f21)); + std::memset(this->f22, 0x00, sizeof(this->f22)); + std::memset(this->f23, 0x00, sizeof(this->f23)); + std::memset(this->f24, 0x00, sizeof(this->f24)); + std::memset(this->f25, 0x00, sizeof(this->f25)); + std::memset(this->f26, 0x00, sizeof(this->f26)); + std::memset(this->f27, 0x00, sizeof(this->f27)); + std::memset(this->f28, 0x00, sizeof(this->f28)); + std::memset(this->f29, 0x00, sizeof(this->f29)); + std::memset(this->f30, 0x00, sizeof(this->f30)); + std::memset(this->f31, 0x00, sizeof(this->f31)); + } + + + riscv32Cpu& riscv32Cpu::operator=(const riscv32Cpu& other) { + this->copy(other); + return *this; + } + + + triton::arch::endianness_e riscv32Cpu::getEndianness(void) const { + return triton::arch::LE_ENDIANNESS; + } + + + bool riscv32Cpu::isRegister(triton::arch::register_e regId) const { + return (this->isGPR(regId) || this->isFPU(regId) || regId == triton::arch::ID_REG_RV32_PC); + } + + + bool riscv32Cpu::isRegisterValid(triton::arch::register_e regId) const { + return (this->isFlag(regId) || this->isRegister(regId)); + } + + + bool riscv32Cpu::isGPR(triton::arch::register_e regId) const { + return ((regId >= triton::arch::ID_REG_RV32_X0 && regId <= triton::arch::ID_REG_RV32_X31) ? true : false); + } + + + bool riscv32Cpu::isFPU(triton::arch::register_e regId) const { + return ((regId >= triton::arch::ID_REG_RV32_F0 && regId <= triton::arch::ID_REG_RV32_F31) ? true : false); + } + + + bool riscv32Cpu::isFlag(triton::arch::register_e regId) const { + return false; + } + + + triton::uint32 riscv32Cpu::numberOfRegisters(void) const { + return triton::arch::ID_REG_LAST_ITEM; + } + + + triton::uint32 riscv32Cpu::gprSize(void) const { + return triton::size::dword; + } + + + triton::uint32 riscv32Cpu::gprBitSize(void) const { + return triton::bitsize::dword; + } + + + const std::unordered_map& riscv32Cpu::getAllRegisters(void) const { + return this->id2reg; + } + + const std::unordered_map>& riscv32Cpu::getConcreteMemory(void) const { + return this->memory; + } + + std::set riscv32Cpu::getParentRegisters(void) const { + std::set ret; + + for (const auto& kv: this->id2reg) { + auto regId = kv.first; + const auto& reg = kv.second; + + /* Add GPR */ + if (reg.getSize() == this->gprSize()) + ret.insert(®); + + /* Add FPU */ + else if (this->isFPU(regId)) + ret.insert(®); + } + + return ret; + } + + + const triton::arch::Register& riscv32Cpu::getRegister(triton::arch::register_e id) const { + try { + return this->id2reg.at(id); + } catch (const std::out_of_range&) { + throw triton::exceptions::Cpu("riscv32Cpu::getRegister(): Invalid register for this architecture."); + } + } + + + const triton::arch::Register& riscv32Cpu::getRegister(const std::string& name) const { + std::string lower = name; + std::transform(lower.begin(), lower.end(), lower.begin(), [](unsigned char c){ return std::tolower(c); }); + try { + return this->getRegister(this->name2id.at(lower)); + } catch (const std::out_of_range&) { + throw triton::exceptions::Cpu("riscv32Cpu::getRegister(): Invalid register for this architecture."); + } + } + + + const triton::arch::Register& riscv32Cpu::getParentRegister(const triton::arch::Register& reg) const { + return this->getRegister(reg.getParent()); + } + + + const triton::arch::Register& riscv32Cpu::getParentRegister(triton::arch::register_e id) const { + return this->getParentRegister(this->getRegister(id)); + } + + + const triton::arch::Register& riscv32Cpu::getProgramCounter(void) const { + return this->getRegister(this->pcId); + } + + + const triton::arch::Register& riscv32Cpu::getStackPointer(void) const { + return this->getRegister(this->spId); + } + + void riscv32Cpu::disassembly(triton::arch::Instruction& inst) { + + triton::extlibs::capstone::cs_insn* insn; + triton::usize count = 0; + triton::uint32 size = 0; + + /* Check if the opcode and opcode' size are defined */ + if (inst.getOpcode() == nullptr || inst.getSize() == 0) + throw triton::exceptions::Disassembly("riscv32Cpu::disassembly(): Opcode and opcodeSize must be definied."); + + /* Clear instructicon's operands if alredy defined */ + inst.operands.clear(); + + /* Update instruction address if undefined */ + if (!inst.getAddress()) { + inst.setAddress(static_cast(this->getConcreteRegisterValue(this->getProgramCounter()))); + } + + /* Let's disass and build our operands */ + count = triton::extlibs::capstone::cs_disasm(this->handle, inst.getOpcode(), inst.getSize(), inst.getAddress(), 0, &insn); + if (count > 0) { + /* Detail information */ + triton::extlibs::capstone::cs_detail* detail = insn->detail; + + /* Init the disassembly */ + std::stringstream str; + + str << insn[0].mnemonic; + if (detail->riscv.op_count) + str << " " << insn[0].op_str; + + inst.setDisassembly(str.str()); + + /* Refine the size */ + inst.setSize(insn[0].size); + + /* Init the instruction's type */ + inst.setType(this->capstoneInstructionToTritonInstruction(insn[0].id)); + + /* Set architecture */ + inst.setArchitecture(triton::arch::ARCH_RV32); + + /* Init operands */ + for (triton::uint32 n = 0; n < detail->riscv.op_count; n++) { + triton::extlibs::capstone::cs_riscv_op* op = &(detail->riscv.operands[n]); + + switch(op->type) { + + case triton::extlibs::capstone::RISCV_OP_IMM: { + triton::arch::Immediate imm(op->imm, size ? size : triton::size::dword); + if (static_cast(op->imm) > imm.getValue()) { + imm = Immediate(); + imm.setValue(op->imm, 0); /* By setting 0 as size, we automatically identify the size of the value */ + } + + inst.operands.push_back(triton::arch::OperandWrapper(imm)); + break; + } + + case triton::extlibs::capstone::RISCV_OP_MEM: { + triton::arch::MemoryAccess mem; + + /* Set the size of the memory access */ + size = this->getMemoryOperandSpecialSize(inst.getType()); + mem.setBits(size ? ((size * triton::bitsize::byte) - 1) : triton::bitsize::dword - 1, 0); + + /* Set address calculation units */ + triton::arch::Register base(*this, this->capstoneRegisterToTritonRegister32(op->mem.base)); + + triton::uint32 immsize = ( + this->isRegisterValid(base.getId()) ? base.getSize() : + this->gprSize() + ); + + triton::arch::Immediate disp(op->mem.disp, immsize); + + mem.setBaseRegister(base); + mem.setDisplacement(disp); + + inst.operands.push_back(triton::arch::OperandWrapper(mem)); + break; + } + + case triton::extlibs::capstone::RISCV_OP_REG: { + inst.operands.push_back(triton::arch::OperandWrapper(triton::arch::Register(*this, this->capstoneRegisterToTritonRegister32(op->reg)))); + break; + } + + default: + throw triton::exceptions::Disassembly("riscv32Cpu::disassembly(): Invalid operand."); + } // switch + } // for operand + + /* Set branch */ + if (detail->groups_count > 0) { + for (triton::uint32 n = 0; n < detail->groups_count; n++) { + if (detail->groups[n] == triton::extlibs::capstone::RISCV_GRP_JUMP) + inst.setBranch(true); + if (detail->groups[n] == triton::extlibs::capstone::RISCV_GRP_JUMP || + detail->groups[n] == triton::extlibs::capstone::RISCV_GRP_CALL || + detail->groups[n] == triton::extlibs::capstone::RISCV_GRP_RET) + inst.setControlFlow(true); + } + } + + /* Free capstone stuffs */ + triton::extlibs::capstone::cs_free(insn, count); + } + else + throw triton::exceptions::Disassembly("riscv32Cpu::disassembly(): Failed to disassemble the given code."); + } + + + triton::uint8 riscv32Cpu::getConcreteMemoryValue(triton::uint64 addr, bool execCallbacks) const { + if (execCallbacks && this->callbacks) + this->callbacks->processCallbacks(triton::callbacks::GET_CONCRETE_MEMORY_VALUE, MemoryAccess(addr, triton::size::byte)); + + auto it = this->memory.find(addr); + if (it == this->memory.end()) { + return 0x00; + } + + return it->second; + } + + + triton::uint512 riscv32Cpu::getConcreteMemoryValue(const triton::arch::MemoryAccess& mem, bool execCallbacks) const { + triton::uint512 ret = 0; + triton::uint64 addr = 0; + triton::uint32 size = 0; + + if (execCallbacks && this->callbacks) + this->callbacks->processCallbacks(triton::callbacks::GET_CONCRETE_MEMORY_VALUE, mem); + + addr = mem.getAddress(); + size = mem.getSize(); + + if (size == 0 || size > triton::size::dqqword) + throw triton::exceptions::Cpu("riscv32Cpu::getConcreteMemoryValue(): Invalid size memory."); + + for (triton::sint32 i = size-1; i >= 0; i--) + ret = ((ret << triton::bitsize::byte) | this->getConcreteMemoryValue(addr+i, false)); + + return ret; + } + + + std::vector riscv32Cpu::getConcreteMemoryAreaValue(triton::uint64 baseAddr, triton::usize size, bool execCallbacks) const { + std::vector area; + + for (triton::usize index = 0; index < size; index++) + area.push_back(this->getConcreteMemoryValue(baseAddr+index, execCallbacks)); + + return area; + } + + + triton::uint512 riscv32Cpu::getConcreteRegisterValue(const triton::arch::Register& reg, bool execCallbacks) const { + triton::uint512 value = 0; + + if (execCallbacks && this->callbacks) + this->callbacks->processCallbacks(triton::callbacks::GET_CONCRETE_REGISTER_VALUE, reg); + switch (reg.getId()) { + case triton::arch::ID_REG_RV32_X0: return 0; + case triton::arch::ID_REG_RV32_X1: return (*((triton::uint32*)(this->x1))); + case triton::arch::ID_REG_RV32_SP: return (*((triton::uint32*)(this->sp))); + case triton::arch::ID_REG_RV32_X3: return (*((triton::uint32*)(this->x3))); + case triton::arch::ID_REG_RV32_X4: return (*((triton::uint32*)(this->x4))); + case triton::arch::ID_REG_RV32_X5: return (*((triton::uint32*)(this->x5))); + case triton::arch::ID_REG_RV32_X6: return (*((triton::uint32*)(this->x6))); + case triton::arch::ID_REG_RV32_X7: return (*((triton::uint32*)(this->x7))); + case triton::arch::ID_REG_RV32_X8: return (*((triton::uint32*)(this->x8))); + case triton::arch::ID_REG_RV32_X9: return (*((triton::uint32*)(this->x9))); + case triton::arch::ID_REG_RV32_X10: return (*((triton::uint32*)(this->x10))); + case triton::arch::ID_REG_RV32_X11: return (*((triton::uint32*)(this->x11))); + case triton::arch::ID_REG_RV32_X12: return (*((triton::uint32*)(this->x12))); + case triton::arch::ID_REG_RV32_X13: return (*((triton::uint32*)(this->x13))); + case triton::arch::ID_REG_RV32_X14: return (*((triton::uint32*)(this->x14))); + case triton::arch::ID_REG_RV32_X15: return (*((triton::uint32*)(this->x15))); + case triton::arch::ID_REG_RV32_X16: return (*((triton::uint32*)(this->x16))); + case triton::arch::ID_REG_RV32_X17: return (*((triton::uint32*)(this->x17))); + case triton::arch::ID_REG_RV32_X18: return (*((triton::uint32*)(this->x18))); + case triton::arch::ID_REG_RV32_X19: return (*((triton::uint32*)(this->x19))); + case triton::arch::ID_REG_RV32_X20: return (*((triton::uint32*)(this->x20))); + case triton::arch::ID_REG_RV32_X21: return (*((triton::uint32*)(this->x21))); + case triton::arch::ID_REG_RV32_X22: return (*((triton::uint32*)(this->x22))); + case triton::arch::ID_REG_RV32_X23: return (*((triton::uint32*)(this->x23))); + case triton::arch::ID_REG_RV32_X24: return (*((triton::uint32*)(this->x24))); + case triton::arch::ID_REG_RV32_X25: return (*((triton::uint32*)(this->x25))); + case triton::arch::ID_REG_RV32_X26: return (*((triton::uint32*)(this->x26))); + case triton::arch::ID_REG_RV32_X27: return (*((triton::uint32*)(this->x27))); + case triton::arch::ID_REG_RV32_X28: return (*((triton::uint32*)(this->x28))); + case triton::arch::ID_REG_RV32_X29: return (*((triton::uint32*)(this->x29))); + case triton::arch::ID_REG_RV32_X30: return (*((triton::uint32*)(this->x30))); + case triton::arch::ID_REG_RV32_X31: return (*((triton::uint32*)(this->x31))); + case triton::arch::ID_REG_RV32_PC: return (*((triton::uint32*)(this->pc))); + case triton::arch::ID_REG_RV32_F0: return (*((triton::uint32*)(this->f0))); + case triton::arch::ID_REG_RV32_F1: return (*((triton::uint32*)(this->f1))); + case triton::arch::ID_REG_RV32_F2: return (*((triton::uint32*)(this->f2))); + case triton::arch::ID_REG_RV32_F3: return (*((triton::uint32*)(this->f3))); + case triton::arch::ID_REG_RV32_F4: return (*((triton::uint32*)(this->f4))); + case triton::arch::ID_REG_RV32_F5: return (*((triton::uint32*)(this->f5))); + case triton::arch::ID_REG_RV32_F6: return (*((triton::uint32*)(this->f6))); + case triton::arch::ID_REG_RV32_F7: return (*((triton::uint32*)(this->f7))); + case triton::arch::ID_REG_RV32_F8: return (*((triton::uint32*)(this->f8))); + case triton::arch::ID_REG_RV32_F9: return (*((triton::uint32*)(this->f9))); + case triton::arch::ID_REG_RV32_F10: return (*((triton::uint32*)(this->f10))); + case triton::arch::ID_REG_RV32_F11: return (*((triton::uint32*)(this->f11))); + case triton::arch::ID_REG_RV32_F12: return (*((triton::uint32*)(this->f12))); + case triton::arch::ID_REG_RV32_F13: return (*((triton::uint32*)(this->f13))); + case triton::arch::ID_REG_RV32_F14: return (*((triton::uint32*)(this->f14))); + case triton::arch::ID_REG_RV32_F15: return (*((triton::uint32*)(this->f15))); + case triton::arch::ID_REG_RV32_F16: return (*((triton::uint32*)(this->f16))); + case triton::arch::ID_REG_RV32_F17: return (*((triton::uint32*)(this->f17))); + case triton::arch::ID_REG_RV32_F18: return (*((triton::uint32*)(this->f18))); + case triton::arch::ID_REG_RV32_F19: return (*((triton::uint32*)(this->f19))); + case triton::arch::ID_REG_RV32_F20: return (*((triton::uint32*)(this->f20))); + case triton::arch::ID_REG_RV32_F21: return (*((triton::uint32*)(this->f21))); + case triton::arch::ID_REG_RV32_F22: return (*((triton::uint32*)(this->f22))); + case triton::arch::ID_REG_RV32_F23: return (*((triton::uint32*)(this->f23))); + case triton::arch::ID_REG_RV32_F24: return (*((triton::uint32*)(this->f24))); + case triton::arch::ID_REG_RV32_F25: return (*((triton::uint32*)(this->f25))); + case triton::arch::ID_REG_RV32_F26: return (*((triton::uint32*)(this->f26))); + case triton::arch::ID_REG_RV32_F27: return (*((triton::uint32*)(this->f27))); + case triton::arch::ID_REG_RV32_F28: return (*((triton::uint32*)(this->f28))); + case triton::arch::ID_REG_RV32_F29: return (*((triton::uint32*)(this->f29))); + case triton::arch::ID_REG_RV32_F30: return (*((triton::uint32*)(this->f30))); + case triton::arch::ID_REG_RV32_F31: return (*((triton::uint32*)(this->f31))); + + default: + throw triton::exceptions::Cpu("riscv32Cpu::getConcreteRegisterValue(): Invalid register."); + } + + return value; + } + + + void riscv32Cpu::setConcreteMemoryValue(triton::uint64 addr, triton::uint8 value, bool execCallbacks) { + if (execCallbacks && this->callbacks) + this->callbacks->processCallbacks(triton::callbacks::SET_CONCRETE_MEMORY_VALUE, MemoryAccess(addr, triton::size::byte), value); + this->memory[addr] = value; + } + + + void riscv32Cpu::setConcreteMemoryValue(const triton::arch::MemoryAccess& mem, const triton::uint512& value, bool execCallbacks) { + triton::uint64 addr = mem.getAddress(); + triton::uint32 size = mem.getSize(); + triton::uint512 cv = value; + + if (cv > mem.getMaxValue()) + throw triton::exceptions::Register("riscv32Cpu::setConcreteMemoryValue(): You cannot set this concrete value (too big) to this memory access."); + + if (size == 0 || size > triton::size::dqqword) + throw triton::exceptions::Cpu("riscv32Cpu::setConcreteMemoryValue(): Invalid size memory."); + + if (execCallbacks && this->callbacks) + this->callbacks->processCallbacks(triton::callbacks::SET_CONCRETE_MEMORY_VALUE, mem, value); + + for (triton::uint32 i = 0; i < size; i++) { + this->memory[addr+i] = static_cast((cv & 0xff)); + cv >>= 8; + } + } + + + void riscv32Cpu::setConcreteMemoryAreaValue(triton::uint64 baseAddr, const std::vector& values, bool execCallbacks) { + // Pre-reserving the memory. We modified the original robin_map to not force rehash on reserve. + this->memory.reserve(values.size() + this->memory.size()); + for (triton::usize index = 0; index < values.size(); index++) { + this->setConcreteMemoryValue(baseAddr+index, values[index], execCallbacks); + } + } + + + void riscv32Cpu::setConcreteMemoryAreaValue(triton::uint64 baseAddr, const void* area, triton::usize size, bool execCallbacks) { + // Pre-reserving the memory. We modified the original robin_map to not force rehash on every reserve if not needed. + this->memory.reserve(size + this->memory.size()); + for (triton::usize index = 0; index < size; index++) { + this->setConcreteMemoryValue(baseAddr+index, reinterpret_cast(area)[index], execCallbacks); + } + } + + + void riscv32Cpu::setConcreteRegisterValue(const triton::arch::Register& reg, const triton::uint512& value, bool execCallbacks) { + if (value > reg.getMaxValue()) + throw triton::exceptions::Register("riscv32Cpu::setConcreteRegisterValue(): You cannot set this concrete value (too big) to this register."); + + if (execCallbacks && this->callbacks) + this->callbacks->processCallbacks(triton::callbacks::SET_CONCRETE_REGISTER_VALUE, reg, value); + + switch (reg.getId()) { + case triton::arch::ID_REG_RV32_X0: break; // Always zero, just do nothing + case triton::arch::ID_REG_RV32_X1: (*((triton::uint32*)(this->x1))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_SP: (*((triton::uint32*)(this->sp))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X3: (*((triton::uint32*)(this->x3))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X4: (*((triton::uint32*)(this->x4))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X5: (*((triton::uint32*)(this->x5))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X6: (*((triton::uint32*)(this->x6))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X7: (*((triton::uint32*)(this->x7))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X8: (*((triton::uint32*)(this->x8))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X9: (*((triton::uint32*)(this->x9))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X10: (*((triton::uint32*)(this->x10))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X11: (*((triton::uint32*)(this->x11))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X12: (*((triton::uint32*)(this->x12))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X13: (*((triton::uint32*)(this->x13))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X14: (*((triton::uint32*)(this->x14))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X15: (*((triton::uint32*)(this->x15))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X16: (*((triton::uint32*)(this->x16))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X17: (*((triton::uint32*)(this->x17))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X18: (*((triton::uint32*)(this->x18))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X19: (*((triton::uint32*)(this->x19))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X20: (*((triton::uint32*)(this->x20))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X21: (*((triton::uint32*)(this->x21))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X22: (*((triton::uint32*)(this->x22))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X23: (*((triton::uint32*)(this->x23))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X24: (*((triton::uint32*)(this->x24))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X25: (*((triton::uint32*)(this->x25))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X26: (*((triton::uint32*)(this->x26))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X27: (*((triton::uint32*)(this->x27))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X28: (*((triton::uint32*)(this->x28))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X29: (*((triton::uint32*)(this->x29))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X30: (*((triton::uint32*)(this->x30))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_X31: (*((triton::uint32*)(this->x31))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_PC: (*((triton::uint32*)(this->pc))) = static_cast(value); break; + + case triton::arch::ID_REG_RV32_F0: (*((triton::uint32*)(this->f0))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F1: (*((triton::uint32*)(this->f1))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F2: (*((triton::uint32*)(this->f2))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F3: (*((triton::uint32*)(this->f3))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F4: (*((triton::uint32*)(this->f4))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F5: (*((triton::uint32*)(this->f5))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F6: (*((triton::uint32*)(this->f6))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F7: (*((triton::uint32*)(this->f7))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F8: (*((triton::uint32*)(this->f8))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F9: (*((triton::uint32*)(this->f9))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F10: (*((triton::uint32*)(this->f10))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F11: (*((triton::uint32*)(this->f11))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F12: (*((triton::uint32*)(this->f12))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F13: (*((triton::uint32*)(this->f13))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F14: (*((triton::uint32*)(this->f14))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F15: (*((triton::uint32*)(this->f15))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F16: (*((triton::uint32*)(this->f16))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F17: (*((triton::uint32*)(this->f17))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F18: (*((triton::uint32*)(this->f18))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F19: (*((triton::uint32*)(this->f19))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F20: (*((triton::uint32*)(this->f20))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F21: (*((triton::uint32*)(this->f21))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F22: (*((triton::uint32*)(this->f22))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F23: (*((triton::uint32*)(this->f23))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F24: (*((triton::uint32*)(this->f24))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F25: (*((triton::uint32*)(this->f25))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F26: (*((triton::uint32*)(this->f26))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F27: (*((triton::uint32*)(this->f27))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F28: (*((triton::uint32*)(this->f28))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F29: (*((triton::uint32*)(this->f29))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F30: (*((triton::uint32*)(this->f30))) = static_cast(value); break; + case triton::arch::ID_REG_RV32_F31: (*((triton::uint32*)(this->f31))) = static_cast(value); break; + + default: + throw triton::exceptions::Cpu("riscv32Cpu:setConcreteRegisterValue(): Invalid register."); + + } + } + + + bool riscv32Cpu::isThumb(void) const { + /* There is no thumb mode in RV */ + return false; + } + + + void riscv32Cpu::setThumb(bool state) { + /* There is no thumb mode in RV */ + } + + + bool riscv32Cpu::isMemoryExclusive(const triton::arch::MemoryAccess& mem) const { + /* There is no exclusive memory access support in RV */ + return false; + } + + + void riscv32Cpu::setMemoryExclusiveTag(const triton::arch::MemoryAccess& mem, bool tag) { + /* There is no exclusive memory access support in RV */ + } + + + bool riscv32Cpu::isConcreteMemoryValueDefined(const triton::arch::MemoryAccess& mem) const { + return this->isConcreteMemoryValueDefined(mem.getAddress(), mem.getSize()); + } + + + bool riscv32Cpu::isConcreteMemoryValueDefined(triton::uint64 baseAddr, triton::usize size) const { + for (triton::usize index = 0; index < size; index++) { + if (this->memory.find(baseAddr + index) == this->memory.end()) { + return false; + } + } + return true; + } + + + void riscv32Cpu::clearConcreteMemoryValue(const triton::arch::MemoryAccess& mem) { + this->clearConcreteMemoryValue(mem.getAddress(), mem.getSize()); + } + + + void riscv32Cpu::clearConcreteMemoryValue(triton::uint64 baseAddr, triton::usize size) { + for (triton::usize index = 0; index < size; index++) { + if (this->memory.find(baseAddr + index) != this->memory.end()) { + this->memory.erase(baseAddr + index); + } + } + } + + }; /* riscv namespace */ + }; /* arch namespace */ +}; /* triton namespace */ diff --git a/src/libtriton/arch/riscv/riscv64Cpu.cpp b/src/libtriton/arch/riscv/riscv64Cpu.cpp new file mode 100644 index 000000000..4f7a90563 --- /dev/null +++ b/src/libtriton/arch/riscv/riscv64Cpu.cpp @@ -0,0 +1,741 @@ +//! \file +/* +** Copyright (C) - Triton +** +** This program is under the terms of the Apache License 2.0. +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + + +namespace triton { + namespace arch { + namespace riscv { + + riscv64Cpu::riscv64Cpu(triton::callbacks::Callbacks* callbacks) : riscvSpecifications(ARCH_RV64) { + this->callbacks = callbacks; + this->handle = 0; + + this->clear(); + this->disassInit(); + } + + + riscv64Cpu::riscv64Cpu(const riscv64Cpu& other) : riscvSpecifications(ARCH_RV64) { + this->copy(other); + } + + + riscv64Cpu::~riscv64Cpu() { + this->memory.clear(); + if (this->handle) { + triton::extlibs::capstone::cs_close(&this->handle); + } + } + + void riscv64Cpu::disassInit(void) { + if (this->handle) { + triton::extlibs::capstone::cs_close(&this->handle); + } + + // CS_MODE_RISCV64 | CS_MODE_RISCVC + auto rv_mode = static_cast((1 << 1) | (1 << 2)); + if (triton::extlibs::capstone::cs_open(triton::extlibs::capstone::CS_ARCH_RISCV, rv_mode, &this->handle) != triton::extlibs::capstone::CS_ERR_OK) + throw triton::exceptions::Disassembly("riscv64Cpu::disassInit(): Cannot open capstone."); + + triton::extlibs::capstone::cs_option(this->handle, triton::extlibs::capstone::CS_OPT_DETAIL, triton::extlibs::capstone::CS_OPT_ON); + } + + + void riscv64Cpu::copy(const riscv64Cpu& other) { + this->callbacks = other.callbacks; + this->memory = other.memory; + + std::memcpy(this->x0, other.x0, sizeof(this->x0)); + std::memcpy(this->x1, other.x1, sizeof(this->x1)); + std::memcpy(this->sp, other.sp, sizeof(this->sp)); + std::memcpy(this->x3, other.x3, sizeof(this->x3)); + std::memcpy(this->x4, other.x4, sizeof(this->x4)); + std::memcpy(this->x5, other.x5, sizeof(this->x5)); + std::memcpy(this->x6, other.x6, sizeof(this->x6)); + std::memcpy(this->x7, other.x7, sizeof(this->x7)); + std::memcpy(this->x8, other.x8, sizeof(this->x8)); + std::memcpy(this->x9, other.x9, sizeof(this->x9)); + std::memcpy(this->x10, other.x10, sizeof(this->x10)); + std::memcpy(this->x11, other.x11, sizeof(this->x11)); + std::memcpy(this->x12, other.x12, sizeof(this->x12)); + std::memcpy(this->x13, other.x13, sizeof(this->x13)); + std::memcpy(this->x14, other.x14, sizeof(this->x14)); + std::memcpy(this->x15, other.x15, sizeof(this->x15)); + std::memcpy(this->x16, other.x16, sizeof(this->x16)); + std::memcpy(this->x17, other.x17, sizeof(this->x17)); + std::memcpy(this->x18, other.x18, sizeof(this->x18)); + std::memcpy(this->x19, other.x19, sizeof(this->x19)); + std::memcpy(this->x20, other.x20, sizeof(this->x20)); + std::memcpy(this->x21, other.x21, sizeof(this->x21)); + std::memcpy(this->x22, other.x22, sizeof(this->x22)); + std::memcpy(this->x23, other.x23, sizeof(this->x23)); + std::memcpy(this->x24, other.x24, sizeof(this->x24)); + std::memcpy(this->x25, other.x25, sizeof(this->x25)); + std::memcpy(this->x26, other.x26, sizeof(this->x26)); + std::memcpy(this->x27, other.x27, sizeof(this->x27)); + std::memcpy(this->x28, other.x28, sizeof(this->x28)); + std::memcpy(this->x29, other.x29, sizeof(this->x29)); + std::memcpy(this->x30, other.x30, sizeof(this->x30)); + std::memcpy(this->x31, other.x31, sizeof(this->x31)); + std::memcpy(this->pc, other.pc, sizeof(this->pc)); + std::memcpy(this->f0, other.f0, sizeof(this->f0)); + std::memcpy(this->f1, other.f1, sizeof(this->f1)); + std::memcpy(this->f2, other.f2, sizeof(this->f2)); + std::memcpy(this->f3, other.f3, sizeof(this->f3)); + std::memcpy(this->f4, other.f4, sizeof(this->f4)); + std::memcpy(this->f5, other.f5, sizeof(this->f5)); + std::memcpy(this->f6, other.f6, sizeof(this->f6)); + std::memcpy(this->f7, other.f7, sizeof(this->f7)); + std::memcpy(this->f8, other.f8, sizeof(this->f8)); + std::memcpy(this->f9, other.f9, sizeof(this->f9)); + std::memcpy(this->f10, other.f10, sizeof(this->f10)); + std::memcpy(this->f11, other.f11, sizeof(this->f11)); + std::memcpy(this->f12, other.f12, sizeof(this->f12)); + std::memcpy(this->f13, other.f13, sizeof(this->f13)); + std::memcpy(this->f14, other.f14, sizeof(this->f14)); + std::memcpy(this->f15, other.f15, sizeof(this->f15)); + std::memcpy(this->f16, other.f16, sizeof(this->f16)); + std::memcpy(this->f17, other.f17, sizeof(this->f17)); + std::memcpy(this->f18, other.f18, sizeof(this->f18)); + std::memcpy(this->f19, other.f19, sizeof(this->f19)); + std::memcpy(this->f20, other.f20, sizeof(this->f20)); + std::memcpy(this->f21, other.f21, sizeof(this->f21)); + std::memcpy(this->f22, other.f22, sizeof(this->f22)); + std::memcpy(this->f23, other.f23, sizeof(this->f23)); + std::memcpy(this->f24, other.f24, sizeof(this->f24)); + std::memcpy(this->f25, other.f25, sizeof(this->f25)); + std::memcpy(this->f26, other.f26, sizeof(this->f26)); + std::memcpy(this->f27, other.f27, sizeof(this->f27)); + std::memcpy(this->f28, other.f28, sizeof(this->f28)); + std::memcpy(this->f29, other.f29, sizeof(this->f29)); + std::memcpy(this->f30, other.f30, sizeof(this->f30)); + std::memcpy(this->f31, other.f31, sizeof(this->f31)); + } + + + void riscv64Cpu::clear(void) { + /* Clear memory */ + this->memory.clear(); + + /* Clear registers */ + std::memset(this->x0, 0x00, sizeof(this->x0)); + std::memset(this->x1, 0x00, sizeof(this->x1)); + std::memset(this->sp, 0x00, sizeof(this->sp)); + std::memset(this->x3, 0x00, sizeof(this->x3)); + std::memset(this->x4, 0x00, sizeof(this->x4)); + std::memset(this->x5, 0x00, sizeof(this->x5)); + std::memset(this->x6, 0x00, sizeof(this->x6)); + std::memset(this->x7, 0x00, sizeof(this->x7)); + std::memset(this->x8, 0x00, sizeof(this->x8)); + std::memset(this->x9, 0x00, sizeof(this->x9)); + std::memset(this->x10, 0x00, sizeof(this->x10)); + std::memset(this->x11, 0x00, sizeof(this->x11)); + std::memset(this->x12, 0x00, sizeof(this->x12)); + std::memset(this->x13, 0x00, sizeof(this->x13)); + std::memset(this->x14, 0x00, sizeof(this->x14)); + std::memset(this->x15, 0x00, sizeof(this->x15)); + std::memset(this->x16, 0x00, sizeof(this->x16)); + std::memset(this->x17, 0x00, sizeof(this->x17)); + std::memset(this->x18, 0x00, sizeof(this->x18)); + std::memset(this->x19, 0x00, sizeof(this->x19)); + std::memset(this->x20, 0x00, sizeof(this->x20)); + std::memset(this->x21, 0x00, sizeof(this->x21)); + std::memset(this->x22, 0x00, sizeof(this->x22)); + std::memset(this->x23, 0x00, sizeof(this->x23)); + std::memset(this->x24, 0x00, sizeof(this->x24)); + std::memset(this->x25, 0x00, sizeof(this->x25)); + std::memset(this->x26, 0x00, sizeof(this->x26)); + std::memset(this->x27, 0x00, sizeof(this->x27)); + std::memset(this->x28, 0x00, sizeof(this->x28)); + std::memset(this->x29, 0x00, sizeof(this->x29)); + std::memset(this->x30, 0x00, sizeof(this->x30)); + std::memset(this->x31, 0x00, sizeof(this->x31)); + std::memset(this->pc, 0x00, sizeof(this->pc)); + std::memset(this->f0, 0x00, sizeof(this->f0)); + std::memset(this->f1, 0x00, sizeof(this->f1)); + std::memset(this->f2, 0x00, sizeof(this->f2)); + std::memset(this->f3, 0x00, sizeof(this->f3)); + std::memset(this->f4, 0x00, sizeof(this->f4)); + std::memset(this->f5, 0x00, sizeof(this->f5)); + std::memset(this->f6, 0x00, sizeof(this->f6)); + std::memset(this->f7, 0x00, sizeof(this->f7)); + std::memset(this->f8, 0x00, sizeof(this->f8)); + std::memset(this->f9, 0x00, sizeof(this->f9)); + std::memset(this->f10, 0x00, sizeof(this->f10)); + std::memset(this->f11, 0x00, sizeof(this->f11)); + std::memset(this->f12, 0x00, sizeof(this->f12)); + std::memset(this->f13, 0x00, sizeof(this->f13)); + std::memset(this->f14, 0x00, sizeof(this->f14)); + std::memset(this->f15, 0x00, sizeof(this->f15)); + std::memset(this->f16, 0x00, sizeof(this->f16)); + std::memset(this->f17, 0x00, sizeof(this->f17)); + std::memset(this->f18, 0x00, sizeof(this->f18)); + std::memset(this->f19, 0x00, sizeof(this->f19)); + std::memset(this->f20, 0x00, sizeof(this->f20)); + std::memset(this->f21, 0x00, sizeof(this->f21)); + std::memset(this->f22, 0x00, sizeof(this->f22)); + std::memset(this->f23, 0x00, sizeof(this->f23)); + std::memset(this->f24, 0x00, sizeof(this->f24)); + std::memset(this->f25, 0x00, sizeof(this->f25)); + std::memset(this->f26, 0x00, sizeof(this->f26)); + std::memset(this->f27, 0x00, sizeof(this->f27)); + std::memset(this->f28, 0x00, sizeof(this->f28)); + std::memset(this->f29, 0x00, sizeof(this->f29)); + std::memset(this->f30, 0x00, sizeof(this->f30)); + std::memset(this->f31, 0x00, sizeof(this->f31)); + } + + + riscv64Cpu& riscv64Cpu::operator=(const riscv64Cpu& other) { + this->copy(other); + return *this; + } + + + triton::arch::endianness_e riscv64Cpu::getEndianness(void) const { + return triton::arch::LE_ENDIANNESS; + } + + + bool riscv64Cpu::isRegister(triton::arch::register_e regId) const { + return (this->isGPR(regId) || this->isFPU(regId) || regId == triton::arch::ID_REG_RV64_PC); + } + + + bool riscv64Cpu::isRegisterValid(triton::arch::register_e regId) const { + return (this->isFlag(regId) || this->isRegister(regId)); + } + + + bool riscv64Cpu::isGPR(triton::arch::register_e regId) const { + return ((regId >= triton::arch::ID_REG_RV64_X0 && regId <= triton::arch::ID_REG_RV64_X31) ? true : false); + } + + + bool riscv64Cpu::isFPU(triton::arch::register_e regId) const { + return ((regId >= triton::arch::ID_REG_RV64_F0 && regId <= triton::arch::ID_REG_RV64_F31) ? true : false); + } + + + bool riscv64Cpu::isFlag(triton::arch::register_e regId) const { + return false; + } + + + triton::uint32 riscv64Cpu::numberOfRegisters(void) const { + return triton::arch::ID_REG_LAST_ITEM; + } + + + triton::uint32 riscv64Cpu::gprSize(void) const { + return triton::size::qword; + } + + + triton::uint32 riscv64Cpu::gprBitSize(void) const { + return triton::bitsize::qword; + } + + + const std::unordered_map& riscv64Cpu::getAllRegisters(void) const { + return this->id2reg; + } + + const std::unordered_map>& riscv64Cpu::getConcreteMemory(void) const { + return this->memory; + } + + std::set riscv64Cpu::getParentRegisters(void) const { + std::set ret; + + for (const auto& kv: this->id2reg) { + auto regId = kv.first; + const auto& reg = kv.second; + + /* Add GPR */ + if (reg.getSize() == this->gprSize()) + ret.insert(®); + + /* Add FPU */ + else if (this->isFPU(regId)) + ret.insert(®); + } + + return ret; + } + + + const triton::arch::Register& riscv64Cpu::getRegister(triton::arch::register_e id) const { + try { + return this->id2reg.at(id); + } catch (const std::out_of_range&) { + throw triton::exceptions::Cpu("riscv64Cpu::getRegister(): Invalid register for this architecture."); + } + } + + + const triton::arch::Register& riscv64Cpu::getRegister(const std::string& name) const { + std::string lower = name; + std::transform(lower.begin(), lower.end(), lower.begin(), [](unsigned char c){ return std::tolower(c); }); + try { + return this->getRegister(this->name2id.at(lower)); + } catch (const std::out_of_range&) { + throw triton::exceptions::Cpu("riscv64Cpu::getRegister(): Invalid register for this architecture."); + } + } + + + const triton::arch::Register& riscv64Cpu::getParentRegister(const triton::arch::Register& reg) const { + return this->getRegister(reg.getParent()); + } + + + const triton::arch::Register& riscv64Cpu::getParentRegister(triton::arch::register_e id) const { + return this->getParentRegister(this->getRegister(id)); + } + + + const triton::arch::Register& riscv64Cpu::getProgramCounter(void) const { + return this->getRegister(this->pcId); + } + + + const triton::arch::Register& riscv64Cpu::getStackPointer(void) const { + return this->getRegister(this->spId); + } + + void riscv64Cpu::disassembly(triton::arch::Instruction& inst) { + + triton::extlibs::capstone::cs_insn* insn; + triton::usize count = 0; + triton::uint32 size = 0; + + /* Check if the opcode and opcode' size are defined */ + if (inst.getOpcode() == nullptr || inst.getSize() == 0) + throw triton::exceptions::Disassembly("riscv64Cpu::disassembly(): Opcode and opcodeSize must be definied."); + + /* Clear instructicon's operands if alredy defined */ + inst.operands.clear(); + + /* Update instruction address if undefined */ + if (!inst.getAddress()) { + inst.setAddress(static_cast(this->getConcreteRegisterValue(this->getProgramCounter()))); + } + + /* Let's disass and build our operands */ + count = triton::extlibs::capstone::cs_disasm(this->handle, inst.getOpcode(), inst.getSize(), inst.getAddress(), 0, &insn); + if (count > 0) { + /* Detail information */ + triton::extlibs::capstone::cs_detail* detail = insn->detail; + + /* Init the disassembly */ + std::stringstream str; + + str << insn[0].mnemonic; + if (detail->riscv.op_count) + str << " " << insn[0].op_str; + + inst.setDisassembly(str.str()); + + /* Refine the size */ + inst.setSize(insn[0].size); + + /* Init the instruction's type */ + inst.setType(this->capstoneInstructionToTritonInstruction(insn[0].id)); + + /* Set architecture */ + inst.setArchitecture(triton::arch::ARCH_RV64); + + /* Init operands */ + for (triton::uint32 n = 0; n < detail->riscv.op_count; n++) { + triton::extlibs::capstone::cs_riscv_op* op = &(detail->riscv.operands[n]); + + switch(op->type) { + + case triton::extlibs::capstone::RISCV_OP_IMM: { + triton::arch::Immediate imm(op->imm, size ? size : triton::size::qword); + if (static_cast(op->imm) > imm.getValue()) { + imm = Immediate(); + imm.setValue(op->imm, 0); /* By setting 0 as size, we automatically identify the size of the value */ + } + + inst.operands.push_back(triton::arch::OperandWrapper(imm)); + break; + } + + case triton::extlibs::capstone::RISCV_OP_MEM: { + triton::arch::MemoryAccess mem; + + /* Set the size of the memory access */ + size = this->getMemoryOperandSpecialSize(inst.getType()); + mem.setBits(size ? ((size * triton::bitsize::byte) - 1) : triton::bitsize::qword - 1, 0); + + /* Set address calculation units */ + triton::arch::Register base(*this, this->capstoneRegisterToTritonRegister64(op->mem.base)); + + triton::uint32 immsize = ( + this->isRegisterValid(base.getId()) ? base.getSize() : + this->gprSize() + ); + + triton::arch::Immediate disp(op->mem.disp, immsize); + + mem.setBaseRegister(base); + mem.setDisplacement(disp); + + inst.operands.push_back(triton::arch::OperandWrapper(mem)); + break; + } + + case triton::extlibs::capstone::RISCV_OP_REG: { + inst.operands.push_back(triton::arch::OperandWrapper(triton::arch::Register(*this, this->capstoneRegisterToTritonRegister64(op->reg)))); + break; + } + + default: + throw triton::exceptions::Disassembly("riscv64Cpu::disassembly(): Invalid operand."); + } // switch + } // for operand + + /* Set branch */ + if (detail->groups_count > 0) { + for (triton::uint32 n = 0; n < detail->groups_count; n++) { + if (detail->groups[n] == triton::extlibs::capstone::RISCV_GRP_JUMP) + inst.setBranch(true); + if (detail->groups[n] == triton::extlibs::capstone::RISCV_GRP_JUMP || + detail->groups[n] == triton::extlibs::capstone::RISCV_GRP_CALL || + detail->groups[n] == triton::extlibs::capstone::RISCV_GRP_RET) + inst.setControlFlow(true); + } + } + + /* Free capstone stuffs */ + triton::extlibs::capstone::cs_free(insn, count); + } + else + throw triton::exceptions::Disassembly("riscv64Cpu::disassembly(): Failed to disassemble the given code."); + } + + + triton::uint8 riscv64Cpu::getConcreteMemoryValue(triton::uint64 addr, bool execCallbacks) const { + if (execCallbacks && this->callbacks) + this->callbacks->processCallbacks(triton::callbacks::GET_CONCRETE_MEMORY_VALUE, MemoryAccess(addr, triton::size::byte)); + + auto it = this->memory.find(addr); + if (it == this->memory.end()) { + return 0x00; + } + + return it->second; + } + + + triton::uint512 riscv64Cpu::getConcreteMemoryValue(const triton::arch::MemoryAccess& mem, bool execCallbacks) const { + triton::uint512 ret = 0; + triton::uint64 addr = 0; + triton::uint32 size = 0; + + if (execCallbacks && this->callbacks) + this->callbacks->processCallbacks(triton::callbacks::GET_CONCRETE_MEMORY_VALUE, mem); + + addr = mem.getAddress(); + size = mem.getSize(); + + if (size == 0 || size > triton::size::dqqword) + throw triton::exceptions::Cpu("riscv64Cpu::getConcreteMemoryValue(): Invalid size memory."); + + for (triton::sint32 i = size-1; i >= 0; i--) + ret = ((ret << triton::bitsize::byte) | this->getConcreteMemoryValue(addr+i, false)); + + return ret; + } + + + std::vector riscv64Cpu::getConcreteMemoryAreaValue(triton::uint64 baseAddr, triton::usize size, bool execCallbacks) const { + std::vector area; + + for (triton::usize index = 0; index < size; index++) + area.push_back(this->getConcreteMemoryValue(baseAddr+index, execCallbacks)); + + return area; + } + + + triton::uint512 riscv64Cpu::getConcreteRegisterValue(const triton::arch::Register& reg, bool execCallbacks) const { + triton::uint512 value = 0; + + if (execCallbacks && this->callbacks) + this->callbacks->processCallbacks(triton::callbacks::GET_CONCRETE_REGISTER_VALUE, reg); + switch (reg.getId()) { + case triton::arch::ID_REG_RV64_X0: return 0; + case triton::arch::ID_REG_RV64_X1: return (*((triton::uint64*)(this->x1))); + case triton::arch::ID_REG_RV64_SP: return (*((triton::uint64*)(this->sp))); + case triton::arch::ID_REG_RV64_X3: return (*((triton::uint64*)(this->x3))); + case triton::arch::ID_REG_RV64_X4: return (*((triton::uint64*)(this->x4))); + case triton::arch::ID_REG_RV64_X5: return (*((triton::uint64*)(this->x5))); + case triton::arch::ID_REG_RV64_X6: return (*((triton::uint64*)(this->x6))); + case triton::arch::ID_REG_RV64_X7: return (*((triton::uint64*)(this->x7))); + case triton::arch::ID_REG_RV64_X8: return (*((triton::uint64*)(this->x8))); + case triton::arch::ID_REG_RV64_X9: return (*((triton::uint64*)(this->x9))); + case triton::arch::ID_REG_RV64_X10: return (*((triton::uint64*)(this->x10))); + case triton::arch::ID_REG_RV64_X11: return (*((triton::uint64*)(this->x11))); + case triton::arch::ID_REG_RV64_X12: return (*((triton::uint64*)(this->x12))); + case triton::arch::ID_REG_RV64_X13: return (*((triton::uint64*)(this->x13))); + case triton::arch::ID_REG_RV64_X14: return (*((triton::uint64*)(this->x14))); + case triton::arch::ID_REG_RV64_X15: return (*((triton::uint64*)(this->x15))); + case triton::arch::ID_REG_RV64_X16: return (*((triton::uint64*)(this->x16))); + case triton::arch::ID_REG_RV64_X17: return (*((triton::uint64*)(this->x17))); + case triton::arch::ID_REG_RV64_X18: return (*((triton::uint64*)(this->x18))); + case triton::arch::ID_REG_RV64_X19: return (*((triton::uint64*)(this->x19))); + case triton::arch::ID_REG_RV64_X20: return (*((triton::uint64*)(this->x20))); + case triton::arch::ID_REG_RV64_X21: return (*((triton::uint64*)(this->x21))); + case triton::arch::ID_REG_RV64_X22: return (*((triton::uint64*)(this->x22))); + case triton::arch::ID_REG_RV64_X23: return (*((triton::uint64*)(this->x23))); + case triton::arch::ID_REG_RV64_X24: return (*((triton::uint64*)(this->x24))); + case triton::arch::ID_REG_RV64_X25: return (*((triton::uint64*)(this->x25))); + case triton::arch::ID_REG_RV64_X26: return (*((triton::uint64*)(this->x26))); + case triton::arch::ID_REG_RV64_X27: return (*((triton::uint64*)(this->x27))); + case triton::arch::ID_REG_RV64_X28: return (*((triton::uint64*)(this->x28))); + case triton::arch::ID_REG_RV64_X29: return (*((triton::uint64*)(this->x29))); + case triton::arch::ID_REG_RV64_X30: return (*((triton::uint64*)(this->x30))); + case triton::arch::ID_REG_RV64_X31: return (*((triton::uint64*)(this->x31))); + case triton::arch::ID_REG_RV64_PC: return (*((triton::uint64*)(this->pc))); + case triton::arch::ID_REG_RV64_F0: return (*((triton::uint64*)(this->f0))); + case triton::arch::ID_REG_RV64_F1: return (*((triton::uint64*)(this->f1))); + case triton::arch::ID_REG_RV64_F2: return (*((triton::uint64*)(this->f2))); + case triton::arch::ID_REG_RV64_F3: return (*((triton::uint64*)(this->f3))); + case triton::arch::ID_REG_RV64_F4: return (*((triton::uint64*)(this->f4))); + case triton::arch::ID_REG_RV64_F5: return (*((triton::uint64*)(this->f5))); + case triton::arch::ID_REG_RV64_F6: return (*((triton::uint64*)(this->f6))); + case triton::arch::ID_REG_RV64_F7: return (*((triton::uint64*)(this->f7))); + case triton::arch::ID_REG_RV64_F8: return (*((triton::uint64*)(this->f8))); + case triton::arch::ID_REG_RV64_F9: return (*((triton::uint64*)(this->f9))); + case triton::arch::ID_REG_RV64_F10: return (*((triton::uint64*)(this->f10))); + case triton::arch::ID_REG_RV64_F11: return (*((triton::uint64*)(this->f11))); + case triton::arch::ID_REG_RV64_F12: return (*((triton::uint64*)(this->f12))); + case triton::arch::ID_REG_RV64_F13: return (*((triton::uint64*)(this->f13))); + case triton::arch::ID_REG_RV64_F14: return (*((triton::uint64*)(this->f14))); + case triton::arch::ID_REG_RV64_F15: return (*((triton::uint64*)(this->f15))); + case triton::arch::ID_REG_RV64_F16: return (*((triton::uint64*)(this->f16))); + case triton::arch::ID_REG_RV64_F17: return (*((triton::uint64*)(this->f17))); + case triton::arch::ID_REG_RV64_F18: return (*((triton::uint64*)(this->f18))); + case triton::arch::ID_REG_RV64_F19: return (*((triton::uint64*)(this->f19))); + case triton::arch::ID_REG_RV64_F20: return (*((triton::uint64*)(this->f20))); + case triton::arch::ID_REG_RV64_F21: return (*((triton::uint64*)(this->f21))); + case triton::arch::ID_REG_RV64_F22: return (*((triton::uint64*)(this->f22))); + case triton::arch::ID_REG_RV64_F23: return (*((triton::uint64*)(this->f23))); + case triton::arch::ID_REG_RV64_F24: return (*((triton::uint64*)(this->f24))); + case triton::arch::ID_REG_RV64_F25: return (*((triton::uint64*)(this->f25))); + case triton::arch::ID_REG_RV64_F26: return (*((triton::uint64*)(this->f26))); + case triton::arch::ID_REG_RV64_F27: return (*((triton::uint64*)(this->f27))); + case triton::arch::ID_REG_RV64_F28: return (*((triton::uint64*)(this->f28))); + case triton::arch::ID_REG_RV64_F29: return (*((triton::uint64*)(this->f29))); + case triton::arch::ID_REG_RV64_F30: return (*((triton::uint64*)(this->f30))); + case triton::arch::ID_REG_RV64_F31: return (*((triton::uint64*)(this->f31))); + + default: + throw triton::exceptions::Cpu("riscv64Cpu::getConcreteRegisterValue(): Invalid register."); + } + + return value; + } + + + void riscv64Cpu::setConcreteMemoryValue(triton::uint64 addr, triton::uint8 value, bool execCallbacks) { + if (execCallbacks && this->callbacks) + this->callbacks->processCallbacks(triton::callbacks::SET_CONCRETE_MEMORY_VALUE, MemoryAccess(addr, triton::size::byte), value); + this->memory[addr] = value; + } + + + void riscv64Cpu::setConcreteMemoryValue(const triton::arch::MemoryAccess& mem, const triton::uint512& value, bool execCallbacks) { + triton::uint64 addr = mem.getAddress(); + triton::uint32 size = mem.getSize(); + triton::uint512 cv = value; + + if (cv > mem.getMaxValue()) + throw triton::exceptions::Register("riscv64Cpu::setConcreteMemoryValue(): You cannot set this concrete value (too big) to this memory access."); + + if (size == 0 || size > triton::size::dqqword) + throw triton::exceptions::Cpu("riscv64Cpu::setConcreteMemoryValue(): Invalid size memory."); + + if (execCallbacks && this->callbacks) + this->callbacks->processCallbacks(triton::callbacks::SET_CONCRETE_MEMORY_VALUE, mem, value); + + for (triton::uint32 i = 0; i < size; i++) { + this->memory[addr+i] = static_cast((cv & 0xff)); + cv >>= 8; + } + } + + + void riscv64Cpu::setConcreteMemoryAreaValue(triton::uint64 baseAddr, const std::vector& values, bool execCallbacks) { + // Pre-reserving the memory. We modified the original robin_map to not force rehash on reserve. + this->memory.reserve(values.size() + this->memory.size()); + for (triton::usize index = 0; index < values.size(); index++) { + this->setConcreteMemoryValue(baseAddr+index, values[index], execCallbacks); + } + } + + + void riscv64Cpu::setConcreteMemoryAreaValue(triton::uint64 baseAddr, const void* area, triton::usize size, bool execCallbacks) { + // Pre-reserving the memory. We modified the original robin_map to not force rehash on every reserve if not needed. + this->memory.reserve(size + this->memory.size()); + for (triton::usize index = 0; index < size; index++) { + this->setConcreteMemoryValue(baseAddr+index, reinterpret_cast(area)[index], execCallbacks); + } + } + + + void riscv64Cpu::setConcreteRegisterValue(const triton::arch::Register& reg, const triton::uint512& value, bool execCallbacks) { + if (value > reg.getMaxValue()) + throw triton::exceptions::Register("riscv64Cpu::setConcreteRegisterValue(): You cannot set this concrete value (too big) to this register."); + + if (execCallbacks && this->callbacks) + this->callbacks->processCallbacks(triton::callbacks::SET_CONCRETE_REGISTER_VALUE, reg, value); + + switch (reg.getId()) { + case triton::arch::ID_REG_RV64_X0: break; // Always zero, just do nothing + case triton::arch::ID_REG_RV64_X1: (*((triton::uint64*)(this->x1))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_SP: (*((triton::uint64*)(this->sp))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X3: (*((triton::uint64*)(this->x3))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X4: (*((triton::uint64*)(this->x4))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X5: (*((triton::uint64*)(this->x5))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X6: (*((triton::uint64*)(this->x6))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X7: (*((triton::uint64*)(this->x7))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X8: (*((triton::uint64*)(this->x8))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X9: (*((triton::uint64*)(this->x9))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X10: (*((triton::uint64*)(this->x10))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X11: (*((triton::uint64*)(this->x11))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X12: (*((triton::uint64*)(this->x12))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X13: (*((triton::uint64*)(this->x13))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X14: (*((triton::uint64*)(this->x14))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X15: (*((triton::uint64*)(this->x15))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X16: (*((triton::uint64*)(this->x16))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X17: (*((triton::uint64*)(this->x17))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X18: (*((triton::uint64*)(this->x18))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X19: (*((triton::uint64*)(this->x19))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X20: (*((triton::uint64*)(this->x20))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X21: (*((triton::uint64*)(this->x21))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X22: (*((triton::uint64*)(this->x22))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X23: (*((triton::uint64*)(this->x23))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X24: (*((triton::uint64*)(this->x24))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X25: (*((triton::uint64*)(this->x25))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X26: (*((triton::uint64*)(this->x26))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X27: (*((triton::uint64*)(this->x27))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X28: (*((triton::uint64*)(this->x28))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X29: (*((triton::uint64*)(this->x29))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X30: (*((triton::uint64*)(this->x30))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_X31: (*((triton::uint64*)(this->x31))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_PC: (*((triton::uint64*)(this->pc))) = static_cast(value); break; + + case triton::arch::ID_REG_RV64_F0: (*((triton::uint64*)(this->f0))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F1: (*((triton::uint64*)(this->f1))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F2: (*((triton::uint64*)(this->f2))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F3: (*((triton::uint64*)(this->f3))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F4: (*((triton::uint64*)(this->f4))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F5: (*((triton::uint64*)(this->f5))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F6: (*((triton::uint64*)(this->f6))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F7: (*((triton::uint64*)(this->f7))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F8: (*((triton::uint64*)(this->f8))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F9: (*((triton::uint64*)(this->f9))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F10: (*((triton::uint64*)(this->f10))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F11: (*((triton::uint64*)(this->f11))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F12: (*((triton::uint64*)(this->f12))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F13: (*((triton::uint64*)(this->f13))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F14: (*((triton::uint64*)(this->f14))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F15: (*((triton::uint64*)(this->f15))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F16: (*((triton::uint64*)(this->f16))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F17: (*((triton::uint64*)(this->f17))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F18: (*((triton::uint64*)(this->f18))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F19: (*((triton::uint64*)(this->f19))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F20: (*((triton::uint64*)(this->f20))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F21: (*((triton::uint64*)(this->f21))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F22: (*((triton::uint64*)(this->f22))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F23: (*((triton::uint64*)(this->f23))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F24: (*((triton::uint64*)(this->f24))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F25: (*((triton::uint64*)(this->f25))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F26: (*((triton::uint64*)(this->f26))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F27: (*((triton::uint64*)(this->f27))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F28: (*((triton::uint64*)(this->f28))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F29: (*((triton::uint64*)(this->f29))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F30: (*((triton::uint64*)(this->f30))) = static_cast(value); break; + case triton::arch::ID_REG_RV64_F31: (*((triton::uint64*)(this->f31))) = static_cast(value); break; + + default: + throw triton::exceptions::Cpu("riscv64Cpu:setConcreteRegisterValue(): Invalid register."); + + } + } + + + bool riscv64Cpu::isThumb(void) const { + /* There is no thumb mode in RV */ + return false; + } + + + void riscv64Cpu::setThumb(bool state) { + /* There is no thumb mode in RV */ + } + + + bool riscv64Cpu::isMemoryExclusive(const triton::arch::MemoryAccess& mem) const { + /* There is no exclusive memory access support in RV */ + return false; + } + + + void riscv64Cpu::setMemoryExclusiveTag(const triton::arch::MemoryAccess& mem, bool tag) { + /* There is no exclusive memory access support in RV */ + } + + + bool riscv64Cpu::isConcreteMemoryValueDefined(const triton::arch::MemoryAccess& mem) const { + return this->isConcreteMemoryValueDefined(mem.getAddress(), mem.getSize()); + } + + + bool riscv64Cpu::isConcreteMemoryValueDefined(triton::uint64 baseAddr, triton::usize size) const { + for (triton::usize index = 0; index < size; index++) { + if (this->memory.find(baseAddr + index) == this->memory.end()) { + return false; + } + } + return true; + } + + + void riscv64Cpu::clearConcreteMemoryValue(const triton::arch::MemoryAccess& mem) { + this->clearConcreteMemoryValue(mem.getAddress(), mem.getSize()); + } + + + void riscv64Cpu::clearConcreteMemoryValue(triton::uint64 baseAddr, triton::usize size) { + for (triton::usize index = 0; index < size; index++) { + if (this->memory.find(baseAddr + index) != this->memory.end()) { + this->memory.erase(baseAddr + index); + } + } + } + + }; /* riscv namespace */ + }; /* arch namespace */ +}; /* triton namespace */ diff --git a/src/libtriton/arch/riscv/riscvSemantics.cpp b/src/libtriton/arch/riscv/riscvSemantics.cpp new file mode 100644 index 000000000..1d73ce09b --- /dev/null +++ b/src/libtriton/arch/riscv/riscvSemantics.cpp @@ -0,0 +1,2650 @@ +//! \file +/* +** Copyright (C) - Triton +** +** This program is under the terms of the Apache License 2.0. +*/ + +#include +#include +#include +#include +#include + + + +/*! \page SMT_Semantics_Supported_page SMT Semantics Supported + \brief [**internal**] All information about the supported semantics. + +- \ref SMT_aarch64_Semantics_Supported_page +- \ref SMT_arm32_Semantics_Supported_page +- \ref SMT_riscv_Semantics_Supported_page +- \ref SMT_x86_Semantics_Supported_page + +*/ + + +/*! \page SMT_riscv_Semantics_Supported_page RV32 and RV64 SMT semantics supported + \brief [**internal**] List of the supported semantics for the RV32 and RV64 architectures. + + +Mnemonic | Description +------------------------------|------------ +ADD | Add (register) +ADDI (pseudo: MV, NOP) | Add (immediate) +ADDIW (pseudo: SEXT.W) | Add word (immediate) / 64-bit only / +ADDW | Add word (register) / 64-bit only / +AND | And (register) +ANDI | And (immediate) +AUIPC | Add upper intermediate to pc +BEQ (pseudo: BEQZ) | Branch if equal +BGE (pseudo: BLEZ, BGEZ) | Branch if greater or equal +BGEU | Branch if greater or equal (unsigned) +BLT (pseudo: BLTZ, BGTZ) | Branch if less +BLTU | Branch if less (unsigned) +BNE (pseudo: BNEZ) | Branch if not equal +DIV | Signed integer division +DIVU | Unsigned integer division +DIVUW | Word unsigned integer division / 64-bit only / +DIVW | Word signed integer division / 64-bit only / +JAL (pseudo: J) | Jump and link +JALR (pseudo: JR, RET) | Jump and link register +LB | Load register signed byte +LBU | Load register unsigned byte +LD | Load register double word / 64-bit only / +LH | Load register signed halfword +LHU | Load register unsigned halfword +LUI | Load upper intermediate +LW | Load register signed word +LWU | Load register unsigned word / 64-bit only / +MUL | Signed multiply +MULH | Signed multiply high +MULHSU | Signed-unsigned multiply high +MULHU | Unsigned multiply high +MULW | Word multiply / 64-bit only / +OR | Or (register) +ORI | Or (immediate) +REM | Signed integer reminder +REMU | Unsigned integer reminder +REMUW | Word unsigned integer reminder / 64-bit only / +REMW | Word signed integer reminder / 64-bit only / +SB | Store register byte +SD | Store register double word / 64-bit only / +SH | Store register halfword +SLL | Logical left shift (register) +SLLI | Logical left shift (immediate) +SLLIW | Word logical left shift (immediate) / 64-bit only / +SLLW | Word logical left shift (register) +SLT (pseudo: SLTZ, SGTZ) | Set if less than register +SLTI | Set if less than immediate +SLTIU (pseudo: SEQZ) | Set if less than immediate (unsigned) +SLTU (pseudo: SNEZ) | Set if less than register (unsigned) +SRA | Arithmetic right shift (register) +SRAI | Arithmetic right shift (immediate) +SRAIW | Word arithmetic right shift (register) / 64-bit only / +SRAW | Word arithmetic right shift (immediate) / 64-bit only / +SRL | Logical right shift (register) +SRLI | Logical right shift (immediate) +SRLIW | Word logical right shift (register) / 64-bit only / +SRLW | Word logical right shift (immediate) / 64-bit only / +SUB (pseudo: NEG) | Subtract +SUBW (pseudo: NEGW) | Subtract word / 64-bit only / +SW | Store register word +XOR | Exclusive or (register) +XORI (pseudo: NOT) | Exclusive or (immediate) +------------------------------|------------ + Compressed instructions +------------------------------|------------ +C.ADD | Add (register) +C.ADDI | Add (immediate) +C.ADDI16SP | Add to SP (immediate, multiplied by 16) +C.ADDI4SPN | Add to SP (immediate, multiplied by 4) +C.ADDIW | Add word (immediate) / 64-bit only / +C.ADDW | Add word (register) / 64-bit only / +C.AND | And (register) +C.ANDI | And (immediate) +C.BEQZ | Branch if equal to zero +C.BNEZ | Branch if not equal to zero +C_J | Jump +C_JAL | Jump and link +C_JALR | Jump and link register +C_JR | Jump register +C_LD | Load register double word / 64-bit only / +C_LDSP | Load register double word from SP / 64-bit only / +C_LI | Load immediate +C_LUI | Load upper intermediate +C_LW | Load register signed word +C_LWSP | Load register word from SP / 64-bit only / +C_MV | Move register +C_NOP | No operation +C.OR | Or (register) +C.SD | Store register double word / 64-bit only / +C.SDSP | Store register double word to SP / 64-bit only / +C.SLLI | Logical left shift (immediate) +C.SRAI | Arithmetic right shift (immediate) +C.SRLI | Logical right shift (immediate) +C.SUB | Subtract +C.SUBW | Subtract word / 64-bit only / +C.SW | Store register word +C.SWSP | Store register word to SP +C.XOR | Exclusive or (register) + +*/ + + +namespace triton { + namespace arch { + namespace riscv { + + riscvSemantics::riscvSemantics(triton::arch::Architecture* architecture, + triton::engines::symbolic::SymbolicEngine* symbolicEngine, + triton::engines::taint::TaintEngine* taintEngine, + const triton::modes::SharedModes& modes, + const triton::ast::SharedAstContext& astCtxt) : modes(modes), astCtxt(astCtxt) { + + this->architecture = architecture; + this->exception = triton::arch::NO_FAULT; + this->symbolicEngine = symbolicEngine; + this->taintEngine = taintEngine; + + if (architecture == nullptr) + throw triton::exceptions::Semantics("riscvSemantics::riscvSemantics(): The architecture API must be defined."); + + if (this->symbolicEngine == nullptr) + throw triton::exceptions::Semantics("riscvSemantics::riscvSemantics(): The symbolic engine API must be defined."); + + if (this->taintEngine == nullptr) + throw triton::exceptions::Semantics("riscvSemantics::riscvSemantics(): The taint engines API must be defined."); + } + + + triton::arch::exception_e riscvSemantics::buildSemantics(triton::arch::Instruction& inst) { + this->exception = triton::arch::NO_FAULT; + switch (inst.getType()) { + case ID_INS_ADD: this->add_s(inst); break; + case ID_INS_ADDI: this->addi_s(inst); break; + case ID_INS_ADDIW: this->addiw_s(inst); break; + case ID_INS_ADDW: this->addw_s(inst); break; + case ID_INS_AND: this->and_s(inst); break; + case ID_INS_ANDI: this->and_s(inst); break; + case ID_INS_AUIPC: this->auipc_s(inst); break; + case ID_INS_BEQ: this->beq_s(inst); break; + case ID_INS_BGE: this->bge_s(inst); break; + case ID_INS_BGEU: this->bgeu_s(inst); break; + case ID_INS_BLT: this->blt_s(inst); break; + case ID_INS_BLTU: this->bltu_s(inst); break; + case ID_INS_BNE: this->bne_s(inst); break; + /* Compressed instructions */ + case ID_INS_C_ADD: this->c_add_s(inst); break; + case ID_INS_C_ADDI: this->c_add_s(inst); break; + case ID_INS_C_ADDI16SP: this->c_addi16sp_s(inst); break; + case ID_INS_C_ADDI4SPN: this->c_addi4spn_s(inst); break; + case ID_INS_C_ADDIW: this->c_addw_s(inst); break; + case ID_INS_C_ADDW: this->c_addw_s(inst); break; + case ID_INS_C_AND: this->c_and_s(inst); break; + case ID_INS_C_ANDI: this->c_and_s(inst); break; + case ID_INS_C_BEQZ: this->c_beqz_s(inst); break; + case ID_INS_C_BNEZ: this->c_bnez_s(inst); break; + case ID_INS_C_J: this->jal_j_s(inst); break; + case ID_INS_C_JAL: this->c_jal_s(inst); break; + case ID_INS_C_JALR: this->c_jalr_s(inst); break; + case ID_INS_C_JR: this->jalr_no_link_s(inst); break; + case ID_INS_C_LD: this->c_ld_s(inst); break; + case ID_INS_C_LDSP: this->c_ldsp_s(inst); break; + case ID_INS_C_LI: this->c_li_s(inst); break; + case ID_INS_C_LW: this->c_lw_s(inst); break; + case ID_INS_C_LWSP: this->c_lwsp_s(inst); break; + case ID_INS_C_LUI: this->lui_s(inst); break; + case ID_INS_C_MV: this->c_mv_s(inst); break; + case ID_INS_C_NOP: this->c_nop_s(inst); break; + case ID_INS_C_OR: this->c_or_s(inst); break; + case ID_INS_C_SD: this->c_sd_s(inst); break; + case ID_INS_C_SDSP: this->c_sdsp_s(inst); break; + case ID_INS_C_SLLI: this->c_slli_s(inst); break; + case ID_INS_C_SRAI: this->c_srai_s(inst); break; + case ID_INS_C_SRLI: this->c_srli_s(inst); break; + case ID_INS_C_SUB: this->c_sub_s(inst); break; + case ID_INS_C_SUBW: this->c_subw_s(inst); break; + case ID_INS_C_SW: this->c_sw_s(inst); break; + case ID_INS_C_SWSP: this->c_swsp_s(inst); break; + case ID_INS_C_XOR: this->c_xor_s(inst); break; + /* End of compressed instructions */ + case ID_INS_DIV: this->div_s(inst); break; + case ID_INS_DIVU: this->divu_s(inst); break; + case ID_INS_DIVUW: this->divuw_s(inst); break; + case ID_INS_DIVW: this->divw_s(inst); break; + case ID_INS_JAL: this->jal_s(inst); break; + case ID_INS_JALR: this->jalr_s(inst); break; + case ID_INS_LB: this->lb_s(inst); break; + case ID_INS_LBU: this->lbu_s(inst); break; + case ID_INS_LD: this->ld_s(inst); break; + case ID_INS_LH: this->lh_s(inst); break; + case ID_INS_LHU: this->lhu_s(inst); break; + case ID_INS_LUI: this->lui_s(inst); break; + case ID_INS_LW: this->lw_s(inst); break; + case ID_INS_LWU: this->lwu_s(inst); break; + case ID_INS_MUL: this->mul_s(inst); break; + case ID_INS_MULH: this->mulh_s(inst); break; + case ID_INS_MULHSU: this->mulhsu_s(inst); break; + case ID_INS_MULHU: this->mulhu_s(inst); break; + case ID_INS_MULW: this->mulw_s(inst); break; + case ID_INS_OR: this->or_s(inst); break; + case ID_INS_ORI: this->or_s(inst); break; + case ID_INS_REM: this->rem_s(inst); break; + case ID_INS_REMU: this->remu_s(inst); break; + case ID_INS_REMUW: this->remuw_s(inst); break; + case ID_INS_REMW: this->remw_s(inst); break; + case ID_INS_SB: this->sb_s(inst); break; + case ID_INS_SD: this->sd_s(inst); break; + case ID_INS_SH: this->sh_s(inst); break; + case ID_INS_SLL: this->sll_s(inst); break; + case ID_INS_SLLI: this->sll_s(inst); break; + case ID_INS_SLLIW: this->sllw_s(inst); break; + case ID_INS_SLLW: this->sllw_s(inst); break; + case ID_INS_SLT: this->slt_s(inst); break; + case ID_INS_SLTI: this->slt_s(inst); break; + case ID_INS_SLTIU: this->sltu_s(inst); break; + case ID_INS_SLTU: this->sltu_s(inst); break; + case ID_INS_SRA: this->sra_s(inst); break; + case ID_INS_SRAI: this->sra_s(inst); break; + case ID_INS_SRAIW: this->sraw_s(inst); break; + case ID_INS_SRAW: this->sraw_s(inst); break; + case ID_INS_SRL: this->srl_s(inst); break; + case ID_INS_SRLI: this->srl_s(inst); break; + case ID_INS_SRLIW: this->srlw_s(inst); break; + case ID_INS_SRLW: this->srlw_s(inst); break; + case ID_INS_SUB: this->sub_s(inst); break; + case ID_INS_SUBW: this->subw_s(inst); break; + case ID_INS_SW: this->sw_s(inst); break; + case ID_INS_XOR: this->xor_s(inst); break; + case ID_INS_XORI: this->xori_s(inst); break; + + default: + this->exception = triton::arch::FAULT_UD; + break; + } + return this->exception; + } + + + void riscvSemantics::controlFlow_s(triton::arch::Instruction& inst) { + auto pc = this->architecture->getProgramCounter(); + auto pc_op = triton::arch::OperandWrapper(pc); + + /* Create the semantics */ + auto node = this->astCtxt->bv(inst.getNextAddress(), pc_op.getBitSize()); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicRegisterExpression(inst, node, pc, "Program Counter"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaintRegister(pc, triton::engines::taint::UNTAINTED); + } + + + void riscvSemantics::add_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + + /* Create the semantics */ + auto node = this->astCtxt->bvadd(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "ADD(I) operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintUnion(src1, src2); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::addi_s(triton::arch::Instruction& inst) { + /* Check for possible pseudo instructions + mv rd, rs -- [addi rd, rs, 0] -- Copy register + nop -- [addi x0, x0, 0] -- No operation + */ + switch (inst.operands.size()) { + case 0: this->controlFlow_s(inst); return; // nop + case 2: addi_mv_s(inst); return; // mv + default: add_s(inst); return; // addi + } + } + + + void riscvSemantics::addi_mv_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "MV operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::addiw_s(triton::arch::Instruction& inst) { /* 64-bit only */ + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto size = dst.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto node = this->astCtxt->sx(32, this->astCtxt->extract(31, 0, op1)); // sext.w pseudo instruction semantics + if (inst.operands.size() > 2) { + auto& src2 = inst.operands[2]; + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + node = this->astCtxt->sx(32, this->astCtxt->extract(31, 0, this->astCtxt->bvadd(op1, op2))); + } + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "ADDIW operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::addw_s(triton::arch::Instruction& inst) { /* 64-bit only */ + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + + /* Create the semantics */ + auto node = this->astCtxt->sx(32, this->astCtxt->bvadd( + this->astCtxt->extract(31, 0, op1), + this->astCtxt->extract(31, 0, op2) + )); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "ADDW operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintUnion(src1, src2); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::and_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + + /* Create the semantics */ + auto node = this->astCtxt->bvand(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "AND(I) operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::auipc_s(triton::arch::Instruction& inst) { + // dst := pc + sx_64(src_imm(_20) << 12) + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + auto pc = triton::arch::OperandWrapper(this->architecture->getProgramCounter()); + + /* Create symbolic operands */ + auto imm = this->symbolicEngine->getOperandAst(inst, src); + auto pc_ast = this->symbolicEngine->getOperandAst(pc); + + /* Create the semantics */ + auto node = this->astCtxt->concat(this->astCtxt->extract(19, 0, imm), this->astCtxt->bv(0, 12)); + if (dst.getBitSize() == 64) { + node = this->astCtxt->sx(32, node); + } + node = this->astCtxt->bvadd(node, pc_ast); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "AUIPC operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(pc); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::beq_s(triton::arch::Instruction& inst) { + /* Check for possible pseudo instructions + beqz rs, offset -- [beq rs, x0, offset] -- Branch if == zero + */ + auto pc = triton::arch::OperandWrapper(this->architecture->getProgramCounter()); + auto& src1 = inst.operands[0]; + auto& src2 = inst.operands[1]; + auto size = src1.getBitSize(); + + /* Create symbolic operands */ + auto pc_ast = this->symbolicEngine->getOperandAst(pc); + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->astCtxt->bv(0, size); + auto op3 = this->symbolicEngine->getOperandAst(inst, src2); + + if (inst.operands.size() == 3) { + auto& imm = inst.operands[2]; + op2 = op3; + op3 = this->symbolicEngine->getOperandAst(inst, imm); + } + + /* Create the semantics */ + auto node = this->astCtxt->ite(this->astCtxt->equal(op1, op2), + this->astCtxt->bvadd(pc_ast, op3), + this->astCtxt->bvadd(pc_ast, this->astCtxt->bv(4, pc.getBitSize())) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, pc, "Program Counter"); + + /* Set condition flag */ + if (op1->evaluate() == op2->evaluate()) + inst.setConditionTaken(true); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(pc); + + /* Create the path constraint */ + this->symbolicEngine->pushPathConstraint(inst, expr); + } + + + void riscvSemantics::bge_s(triton::arch::Instruction& inst) { + /* Check for possible pseudo instructions (no ble in capstone) + blez rs, offset -- [bge x0, rs, offset] -- Branch if <= zero + bgez rs, offset -- [bge rs, x0, offset] -- Branch if >= zero + */ + auto pc = triton::arch::OperandWrapper(this->architecture->getProgramCounter()); + auto& src1 = inst.operands[0]; + auto& src2 = inst.operands[1]; + auto size = src1.getBitSize(); + + /* Create symbolic operands */ + auto pc_ast = this->symbolicEngine->getOperandAst(pc); + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->astCtxt->bv(0, size); + auto op3 = this->symbolicEngine->getOperandAst(inst, src2); + + /* Create branch condition AST */ + auto node = this->astCtxt->bvsge(op1, op2); // bgez + if (inst.operands.size() < 3) { + auto mnem = inst.getDisassembly(); + if (mnem[1] == 'l') { // blez + node = this->astCtxt->bvsle(op1, op2); + } + } + else { // bge + auto& imm = inst.operands[2]; + op2 = op3; + op3 = this->symbolicEngine->getOperandAst(inst, imm); + node = this->astCtxt->bvsge(op1, op2); + } + + /* Create the semantics */ + node = this->astCtxt->ite(node, + this->astCtxt->bvadd(pc_ast, op3), + this->astCtxt->bvadd(pc_ast, this->astCtxt->bv(4, pc.getBitSize())) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, pc, "Program Counter"); + + /* Set condition flag */ + if ((long long)(op1->evaluate() - op2->evaluate()) >= 0) + inst.setConditionTaken(true); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(pc); + + /* Create the path constraint */ + this->symbolicEngine->pushPathConstraint(inst, expr); + } + + + void riscvSemantics::bgeu_s(triton::arch::Instruction& inst) { + auto pc = triton::arch::OperandWrapper(this->architecture->getProgramCounter()); + auto& src1 = inst.operands[0]; + auto& src2 = inst.operands[1]; + auto& imm = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + auto op3 = this->symbolicEngine->getOperandAst(inst, imm); + auto pc_ast = this->symbolicEngine->getOperandAst(pc); + + /* Create the semantics */ + auto node = this->astCtxt->ite(this->astCtxt->bvuge(op1, op2), + this->astCtxt->bvadd(pc_ast, op3), + this->astCtxt->bvadd(pc_ast, this->astCtxt->bv(4, pc.getBitSize())) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, pc, "Program Counter"); + + /* Set condition flag */ + if (op1->evaluate() >= op2->evaluate()) + inst.setConditionTaken(true); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(pc); + + /* Create the path constraint */ + this->symbolicEngine->pushPathConstraint(inst, expr); + } + + + void riscvSemantics::blt_s(triton::arch::Instruction& inst) { + /* Check for possible pseudo instructions (no bgt in capstone) + bltz rs, offset -- [blt rs, x0, offset] -- Branch if < zero + bgtz rs, offset -- [blt x0, rs, offset] -- Branch if > zero + */ + auto pc = triton::arch::OperandWrapper(this->architecture->getProgramCounter()); + auto& src1 = inst.operands[0]; + auto& src2 = inst.operands[1]; + auto size = src1.getBitSize(); + + /* Create symbolic operands */ + auto pc_ast = this->symbolicEngine->getOperandAst(pc); + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->astCtxt->bv(0, size); + auto op3 = this->symbolicEngine->getOperandAst(inst, src2); + + /* Create branch condition AST */ + auto node = this->astCtxt->bvslt(op1, op2); // bltz + if (inst.operands.size() < 3) { + auto mnem = inst.getDisassembly(); + if (mnem[1] == 'l') { // bgtz + node = this->astCtxt->bvsgt(op1, op2); + } + } + else { // blt + auto& imm = inst.operands[2]; + op2 = op3; + op3 = this->symbolicEngine->getOperandAst(inst, imm); + node = this->astCtxt->bvslt(op1, op2); + } + + /* Create the semantics */ + node = this->astCtxt->ite(node, + this->astCtxt->bvadd(pc_ast, op3), + this->astCtxt->bvadd(pc_ast, this->astCtxt->bv(4, pc.getBitSize())) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, pc, "Program Counter"); + + /* Set condition flag */ + if ((long long)(op1->evaluate() - op2->evaluate()) >= 0) + inst.setConditionTaken(true); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(pc); + + /* Create the path constraint */ + this->symbolicEngine->pushPathConstraint(inst, expr); + } + + + void riscvSemantics::bltu_s(triton::arch::Instruction& inst) { + auto pc = triton::arch::OperandWrapper(this->architecture->getProgramCounter()); + auto& src1 = inst.operands[0]; + auto& src2 = inst.operands[1]; + auto& imm = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + auto op3 = this->symbolicEngine->getOperandAst(inst, imm); + auto pc_ast = this->symbolicEngine->getOperandAst(pc); + + /* Create the semantics */ + auto node = this->astCtxt->ite(this->astCtxt->bvult(op1, op2), + this->astCtxt->bvadd(pc_ast, op3), + this->astCtxt->bvadd(pc_ast, this->astCtxt->bv(4, pc.getBitSize())) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, pc, "Program Counter"); + + /* Set condition flag */ + if (op2->evaluate() > op1->evaluate()) + inst.setConditionTaken(true); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(pc); + + /* Create the path constraint */ + this->symbolicEngine->pushPathConstraint(inst, expr); + } + + + void riscvSemantics::bne_s(triton::arch::Instruction& inst) { + /* Check for possible pseudo instructions + bnez rs, offset -- [blt rs, x0, offset] -- Branch if != zero + */ + auto pc = triton::arch::OperandWrapper(this->architecture->getProgramCounter()); + auto& src1 = inst.operands[0]; + auto& src2 = inst.operands[1]; + auto size = src1.getBitSize(); + + /* Create symbolic operands */ + auto pc_ast = this->symbolicEngine->getOperandAst(pc); + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->astCtxt->bv(0, size); + auto op3 = this->symbolicEngine->getOperandAst(inst, src2); + + if (inst.operands.size() == 3) { + auto& imm = inst.operands[2]; + op2 = op3; + op3 = this->symbolicEngine->getOperandAst(inst, imm); + } + + /* Create the semantics */ + auto node = this->astCtxt->ite(this->astCtxt->equal(op1, op2), + this->astCtxt->bvadd(pc_ast, this->astCtxt->bv(4, pc.getBitSize())), + this->astCtxt->bvadd(pc_ast, op3) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, pc, "Program Counter"); + + /* Set condition flag */ + if (op1->evaluate() - op2->evaluate()) + inst.setConditionTaken(true); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(pc); + + /* Create the path constraint */ + this->symbolicEngine->pushPathConstraint(inst, expr); + } + + + // Compressed instructions: + void riscvSemantics::c_add_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, dst); + auto op2 = this->symbolicEngine->getOperandAst(inst, src); + + /* Create the semantics */ + auto node = this->astCtxt->bvadd(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.ADD(I) operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintUnion(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_addi16sp_s(triton::arch::Instruction& inst) { + auto& sp = inst.operands[0]; + auto& imm = inst.operands[1]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, sp); + auto op2 = this->symbolicEngine->getOperandAst(inst, imm); + + /* Create the semantics */ + auto node = this->astCtxt->bvadd(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, sp, "C.ADDI16SP operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(sp); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_addi4spn_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + auto& imm = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src); + auto op2 = this->symbolicEngine->getOperandAst(inst, imm); + + /* Create the semantics */ + auto node = this->astCtxt->bvadd(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.ADDI4SPN operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_addw_s(triton::arch::Instruction& inst) { /* 64-bit only */ + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, dst); + auto op2 = this->symbolicEngine->getOperandAst(inst, src); + + /* Create the semantics */ + auto node = this->astCtxt->sx(32, this->astCtxt->bvadd( + this->astCtxt->extract(31, 0, op1), + this->astCtxt->extract(31, 0, op2) + )); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.ADD(I)W operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintUnion(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_and_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, dst); + auto op2 = this->symbolicEngine->getOperandAst(inst, src); + + /* Create the semantics */ + auto node = this->astCtxt->bvand(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.AND(I) operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintUnion(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_beqz_s(triton::arch::Instruction& inst) { + auto pc = triton::arch::OperandWrapper(this->architecture->getProgramCounter()); + auto& src1 = inst.operands[0]; + auto& src2 = inst.operands[1]; + auto size = src1.getBitSize(); + + /* Create symbolic operands */ + auto pc_ast = this->symbolicEngine->getOperandAst(pc); + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->astCtxt->bv(0, size); + auto op3 = this->symbolicEngine->getOperandAst(inst, src2); + + /* Create the semantics */ + auto node = this->astCtxt->ite(this->astCtxt->equal(op1, op2), + this->astCtxt->bvadd(pc_ast, op3), + this->astCtxt->bvadd(pc_ast, this->astCtxt->bv(2, pc.getBitSize())) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, pc, "Program Counter"); + + /* Set condition flag */ + if (op1->evaluate() == 0) + inst.setConditionTaken(true); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(pc); + + /* Create the path constraint */ + this->symbolicEngine->pushPathConstraint(inst, expr); + } + + + void riscvSemantics::c_bnez_s(triton::arch::Instruction& inst) { + auto pc = triton::arch::OperandWrapper(this->architecture->getProgramCounter()); + auto& src1 = inst.operands[0]; + auto& src2 = inst.operands[1]; + auto size = src1.getBitSize(); + + /* Create symbolic operands */ + auto pc_ast = this->symbolicEngine->getOperandAst(pc); + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->astCtxt->bv(0, size); + auto op3 = this->symbolicEngine->getOperandAst(inst, src2); + + /* Create the semantics */ + auto node = this->astCtxt->ite(this->astCtxt->equal(op1, op2), + this->astCtxt->bvadd(pc_ast, this->astCtxt->bv(2, pc.getBitSize())), + this->astCtxt->bvadd(pc_ast, op3) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, pc, "Program Counter"); + + /* Set condition flag */ + if (op1->evaluate() != 0) + inst.setConditionTaken(true); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(pc); + + /* Create the path constraint */ + this->symbolicEngine->pushPathConstraint(inst, expr); + } + + + void riscvSemantics::c_jal_s(triton::arch::Instruction& inst) { /* 32-bit only */ + /* x1 := pc + 2; pc := pc + offset + Compressed instruction expands to: + jal offset -- [jal x1, offset] -- Jump and link + */ + auto pc = triton::arch::OperandWrapper(this->architecture->getProgramCounter()); + auto size = pc.getBitSize(); + auto& src = inst.operands[0]; + auto ra = this->architecture->getRegister(triton::arch::ID_REG_RV32_X1); + auto reg = triton::arch::OperandWrapper(ra); + + /* Create symbolic operands */ + auto pc_ast = this->symbolicEngine->getOperandAst(pc); + auto imm = this->symbolicEngine->getOperandAst(inst, src); + + /* Create the semantics */ + auto node = this->astCtxt->bvadd(pc_ast, this->astCtxt->bv(2, size)); + auto node_pc = this->astCtxt->bvadd(pc_ast, imm); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, reg, "C.JAL operation ra (x1)"); + auto expr_pc = this->symbolicEngine->createSymbolicExpression(inst, node_pc, pc, "Program Counter"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(pc); + expr_pc->isTainted = this->taintEngine->isTainted(pc); + + /* Create the path constraint */ + this->symbolicEngine->pushPathConstraint(inst, expr_pc); + } + + + void riscvSemantics::c_jalr_s(triton::arch::Instruction& inst) { + /* x1 := pc + 2; pc := (x[rs] + imm) & ~1 + Compressed instruction expands to: + jalr rs -- [jalr x1, rs, 0] -- Jump and link register + */ + auto pc = triton::arch::OperandWrapper(this->architecture->getProgramCounter()); + auto size = pc.getBitSize(); + auto& src = inst.operands[0]; + auto ra = this->architecture->getRegister( + size == 64 ? + triton::arch::ID_REG_RV64_X1 : + triton::arch::ID_REG_RV32_X1 + ); + auto dst = triton::arch::OperandWrapper(ra); + + /* Create symbolic operands */ + auto pc_ast = this->symbolicEngine->getOperandAst(pc); + auto op_src = this->symbolicEngine->getOperandAst(inst, src); + + /* Create the semantics */ + auto node_dst = this->astCtxt->bvadd(pc_ast, this->astCtxt->bv(2, size)); + auto node_pc = this->astCtxt->bvand( /* ignore last bit */ + op_src, + this->astCtxt->bvshl(this->astCtxt->bv(-1, size), this->astCtxt->bv(1, size)) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node_dst, dst, "C.JALR operation ra (x1)"); + auto expr_pc = this->symbolicEngine->createSymbolicExpression(inst, node_pc, pc, "Program Counter"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(pc); + expr_pc->isTainted = this->taintEngine->isTainted(src); + + /* Create the path constraint */ + this->symbolicEngine->pushPathConstraint(inst, expr_pc); + } + + + void riscvSemantics::c_ld_s(triton::arch::Instruction& inst) { /* 64-bit only */ + // x[rd] := M[sp + offset][63:0] + auto& dst = inst.operands[0]; // rd + auto& src1 = inst.operands[1]; // offset - disp + auto& src2 = inst.operands[2]; // rs1 - base + + /* Construct double word memory access manually with base and displacement */ + triton::arch::MemoryAccess mem; + mem.setBits(triton::bitsize::qword - 1, 0); + triton::arch::Immediate& disp = src1.getImmediate(); + triton::arch::Register& base = src2.getRegister(); + mem.setBaseRegister(base); + mem.setDisplacement(disp); + auto mem_op = triton::arch::OperandWrapper(mem); + this->symbolicEngine->initLeaAst(mem_op.getMemory()); + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, mem_op); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.LD operation - LOAD access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, mem_op); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_ldsp_s(triton::arch::Instruction& inst) { /* 64-bit only */ + // x[rd] := M[sp + offset][63:0] + auto& dst = inst.operands[0]; // rd + auto& src1 = inst.operands[1]; // offset - disp; (sp - base) + + /* Construct double word memory access manually with base and displacement */ + triton::arch::MemoryAccess mem; + mem.setBits(triton::bitsize::qword - 1, 0); + triton::arch::Immediate& disp = src1.getImmediate(); + auto sp = this->architecture->getStackPointer(); + mem.setBaseRegister(sp); + mem.setDisplacement(disp); + auto mem_op = triton::arch::OperandWrapper(mem); + this->symbolicEngine->initLeaAst(mem_op.getMemory()); + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, mem_op); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.LDSP operation - LOAD access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, mem_op); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_li_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.LI operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_lw_s(triton::arch::Instruction& inst) { + // x[rd] := M[x[rs] + offset][31:0] + auto& dst = inst.operands[0]; // rd + auto& src1 = inst.operands[1]; // offset - disp + auto& src2 = inst.operands[2]; // rs1 - base + + /* Construct word memory access manually with base and displacement */ + triton::arch::MemoryAccess mem; + mem.setBits(triton::bitsize::dword - 1, 0); + triton::arch::Immediate& disp = src1.getImmediate(); + triton::arch::Register& base = src2.getRegister(); + mem.setBaseRegister(base); + mem.setDisplacement(disp); + auto mem_op = triton::arch::OperandWrapper(mem); + this->symbolicEngine->initLeaAst(mem_op.getMemory()); + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, mem_op); + if (dst.getBitSize() == 64) { /* extend to register size */ + node = this->astCtxt->sx(32, node); + } + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.LW operation - LOAD access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, mem_op); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_lwsp_s(triton::arch::Instruction& inst) { + // x[rd] := M[sp + offset][31:0] + auto& dst = inst.operands[0]; // rd + auto& src = inst.operands[1]; // offset - disp; (sp - base) + + /* Construct word memory access manually with base and displacement */ + triton::arch::MemoryAccess mem; + mem.setBits(triton::bitsize::dword - 1, 0); + triton::arch::Immediate& disp = src.getImmediate(); + auto sp = this->architecture->getStackPointer(); + mem.setBaseRegister(sp); + mem.setDisplacement(disp); + auto mem_op = triton::arch::OperandWrapper(mem); + this->symbolicEngine->initLeaAst(mem_op.getMemory()); + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, mem_op); + if (dst.getBitSize() == 64) { /* extend to register size */ + node = this->astCtxt->sx(32, node); + } + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.LWSP operation - LOAD access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, mem_op); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_mv_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.MV operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_nop_s(triton::arch::Instruction& inst) { + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_or_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, dst); + auto op2 = this->symbolicEngine->getOperandAst(inst, src); + + /* Create the semantics */ + auto node = this->astCtxt->bvor(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.OR operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(dst) | this->taintEngine->isTainted(src)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_sd_s(triton::arch::Instruction& inst) { /* 64-bit only */ + // M[x[rs1] + offset] := x[rs2] + auto& src = inst.operands[0]; // rs2 + auto& imm = inst.operands[1]; // offset - disp + auto& dst = inst.operands[2]; // rs1 - base + + /* Construct double word memory access manually with base and displacement */ + triton::arch::MemoryAccess mem; + mem.setBits(triton::bitsize::qword - 1, 0); + triton::arch::Immediate& disp = imm.getImmediate(); + triton::arch::Register& base = dst.getRegister(); + mem.setBaseRegister(base); + mem.setDisplacement(disp); + auto mem_op = triton::arch::OperandWrapper(mem); + this->symbolicEngine->initLeaAst(mem_op.getMemory()); + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, mem_op, "C.SD operation - STORE access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(mem_op, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_sdsp_s(triton::arch::Instruction& inst) { /* 64-bit only */ + // M[sp + offset] := x[rs] + auto& src = inst.operands[0]; // rs + auto& imm = inst.operands[1]; // offset - disp; (sp - base) + + /* Construct double word memory access manually with base and displacement */ + triton::arch::MemoryAccess mem; + mem.setBits(triton::bitsize::qword - 1, 0); + triton::arch::Immediate& disp = imm.getImmediate(); + auto sp = this->architecture->getStackPointer(); + mem.setBaseRegister(sp); + mem.setDisplacement(disp); + auto mem_op = triton::arch::OperandWrapper(mem); + this->symbolicEngine->initLeaAst(mem_op.getMemory()); + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, mem_op, "C.SDSP operation - STORE access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(mem_op, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_slli_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + auto size = src.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, dst); + auto op2 = this->astCtxt->bvand( + this->symbolicEngine->getOperandAst(inst, src), + dst.getBitSize() == 64 ? this->astCtxt->bv(0x1f, size) : this->astCtxt->bv(0x0f, size) + ); + + /* Create the semantics */ + auto node = this->astCtxt->bvshl(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.SLLI operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintUnion(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_srai_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + auto size = src.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, dst); + auto op2 = this->astCtxt->bvand( + this->symbolicEngine->getOperandAst(inst, src), + dst.getBitSize() == 64 ? this->astCtxt->bv(0x1f, size) : this->astCtxt->bv(0x0f, size) + ); + + /* Create the semantics */ + auto node = this->astCtxt->bvashr(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.SRAI operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintUnion(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_srli_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + auto size = src.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, dst); + auto op2 = this->astCtxt->bvand( + this->symbolicEngine->getOperandAst(inst, src), + dst.getBitSize() == 64 ? this->astCtxt->bv(0x1f, size) : this->astCtxt->bv(0x0f, size) + ); + + /* Create the semantics */ + auto node = this->astCtxt->bvlshr(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.SRLI operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintUnion(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_sub_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, dst); + auto op2 = this->symbolicEngine->getOperandAst(inst, src); + + /* Create the semantics */ + auto node = this->astCtxt->bvsub(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.SUB operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintUnion(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_subw_s(triton::arch::Instruction& inst) { /* 64-bit only */ + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + + /* Create symbolic operands */ + auto op1 = this->astCtxt->extract(31, 0, this->symbolicEngine->getOperandAst(inst, dst)); + auto op2 = this->astCtxt->extract(31, 0, this->symbolicEngine->getOperandAst(inst, src)); + + /* Create the semantics */ + auto node = this->astCtxt->sx(32, this->astCtxt->bvsub(op1, op2)); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.SUBW operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintUnion(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_sw_s(triton::arch::Instruction& inst) { + // M[x[rs1] + offset] := (x[rs2] & 0xffffffff) + auto& src = inst.operands[0]; // rs2 + auto& imm = inst.operands[1]; // offset - disp + auto& dst = inst.operands[2]; // rs1 - base + + /* Construct double word memory access manually with base and displacement */ + triton::arch::MemoryAccess mem; + mem.setBits(triton::bitsize::dword - 1, 0); + triton::arch::Immediate& disp = imm.getImmediate(); + triton::arch::Register& base = dst.getRegister(); + mem.setBaseRegister(base); + mem.setDisplacement(disp); + auto mem_op = triton::arch::OperandWrapper(mem); + this->symbolicEngine->initLeaAst(mem_op.getMemory()); + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + if (src.getBitSize() == 64) { + node = this->astCtxt->extract(31, 0, node); + } + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, mem_op, "C.SW operation - STORE access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(mem_op, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_swsp_s(triton::arch::Instruction& inst) { + // M[sp + offset] := (x[rs] & 0xffffffff) + auto& src = inst.operands[0]; // rs + auto& imm = inst.operands[1]; // offset - disp; (sp - base) + + /* Construct double word memory access manually with base and displacement */ + triton::arch::MemoryAccess mem; + mem.setBits(triton::bitsize::dword - 1, 0); + triton::arch::Immediate& disp = imm.getImmediate(); + auto sp = this->architecture->getStackPointer(); + mem.setBaseRegister(sp); + mem.setDisplacement(disp); + auto mem_op = triton::arch::OperandWrapper(mem); + this->symbolicEngine->initLeaAst(mem_op.getMemory()); + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + if (src.getBitSize() == 64) { + node = this->astCtxt->extract(31, 0, node); + } + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, mem_op, "C.SWSP operation - STORE access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(mem_op, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::c_xor_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, dst); + auto op2 = this->symbolicEngine->getOperandAst(inst, src); + + /* Create the semantics */ + auto node = this->astCtxt->bvxor(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "C.XOR operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::div_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + + /* Create the semantics */ + auto node = this->astCtxt->ite( + this->astCtxt->equal(op2, this->astCtxt->bv(0, op2->getBitvectorSize())), + this->astCtxt->bv(0, dst.getBitSize()), + this->astCtxt->bvsdiv(op1, op2) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "DIV operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::divu_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + + /* Create the semantics */ + auto node = this->astCtxt->ite( + this->astCtxt->equal(op2, this->astCtxt->bv(0, op2->getBitvectorSize())), + this->astCtxt->bv(0, dst.getBitSize()), + this->astCtxt->bvudiv(op1, op2) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "DIVU operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::divuw_s(triton::arch::Instruction& inst) { /* 64-bit only */ + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->astCtxt->extract(31, 0, this->symbolicEngine->getOperandAst(inst, src1)); + auto op2 = this->astCtxt->extract(31, 0, this->symbolicEngine->getOperandAst(inst, src2)); + + /* Create the semantics */ + auto node = this->astCtxt->ite( + this->astCtxt->equal(op2, this->astCtxt->bv(0, op2->getBitvectorSize())), + this->astCtxt->bv(0, dst.getBitSize()), + this->astCtxt->sx(32, this->astCtxt->bvudiv(op1, op2)) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "DIVUW operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::divw_s(triton::arch::Instruction& inst) { /* 64-bit only */ + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->astCtxt->extract(31, 0, this->symbolicEngine->getOperandAst(inst, src1)); + auto op2 = this->astCtxt->extract(31, 0, this->symbolicEngine->getOperandAst(inst, src2)); + + /* Create the semantics */ + auto node = this->astCtxt->ite( + this->astCtxt->equal(op2, this->astCtxt->bv(0, op2->getBitvectorSize())), + this->astCtxt->bv(0, dst.getBitSize()), + this->astCtxt->sx(32, this->astCtxt->bvsdiv(op1, op2)) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "DIVW operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + void riscvSemantics::jal_s(triton::arch::Instruction& inst) { + /* Check for possible pseudo instructions + j offset -- [jal x0, offset] -- Jump + jal offset -- [jal x1, offset] -- Jump and link + */ + auto mnem = inst.getDisassembly(); + if (mnem[1] == ' ') { + jal_j_s(inst); + return; + } + + auto pc = triton::arch::OperandWrapper(this->architecture->getProgramCounter()); + auto size = pc.getBitSize(); + + auto ra = this->architecture->getRegister( + size == 64 ? + triton::arch::ID_REG_RV64_X1 : + triton::arch::ID_REG_RV32_X1 + ); + auto reg = triton::arch::OperandWrapper(ra); + auto& src1 = inst.operands[0]; + + /* Create symbolic operands */ + auto pc_ast = this->symbolicEngine->getOperandAst(pc); + auto imm = this->symbolicEngine->getOperandAst(inst, src1); + if (src1.getType() == triton::arch::OP_REG) { + auto& src2 = inst.operands[1]; + reg = src1; + imm = this->symbolicEngine->getOperandAst(inst, src2); + } + + /* Create the semantics */ + auto node = this->astCtxt->bvadd(pc_ast, this->astCtxt->bv(4, size)); + auto node_pc = this->astCtxt->bvadd(pc_ast, imm); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, reg, "JAL operation ret addr"); + auto expr_pc = this->symbolicEngine->createSymbolicExpression(inst, node_pc, pc, "Program Counter"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(pc); + expr_pc->isTainted = this->taintEngine->isTainted(pc); + + /* Create the path constraint */ + this->symbolicEngine->pushPathConstraint(inst, expr_pc); + } + + + void riscvSemantics::jal_j_s(triton::arch::Instruction& inst) { + auto pc = triton::arch::OperandWrapper(this->architecture->getProgramCounter()); + auto& src1 = inst.operands[0]; + auto size = pc.getBitSize(); + + /* Create symbolic operands */ + auto pc_ast = this->symbolicEngine->getOperandAst(pc); + auto imm = this->symbolicEngine->getOperandAst(inst, src1); + + /* Create the semantics */ + auto node_pc = this->astCtxt->bvadd(pc_ast, imm); + + /* Create symbolic expression */ + auto expr_pc = this->symbolicEngine->createSymbolicExpression(inst, node_pc, pc, "Program Counter"); + + /* Spread taint */ + expr_pc->isTainted = this->taintEngine->isTainted(pc); + + /* Create the path constraint */ + this->symbolicEngine->pushPathConstraint(inst, expr_pc); + } + + + void riscvSemantics::jalr_s(triton::arch::Instruction& inst) { + /* x[rd] := pc + 4; pc := (x[rs] + imm) & ~1 + /* Check for possible pseudo instructions + ret -- [jalr x0, x1, 0] -- Return from subroutine + jr rs -- [jalr x0, rs, 0] -- Jump register + jalr rs -- [jalr x1, rs, 0] -- Jump and link register + */ + auto mnem = inst.getDisassembly(); + if (mnem[2] != 'l') { jalr_no_link_s(inst); return; } // ret & jr semantics + + auto pc = triton::arch::OperandWrapper(this->architecture->getProgramCounter()); + auto size = pc.getBitSize(); + auto ra = this->architecture->getRegister( + size == 64 ? + triton::arch::ID_REG_RV64_X1 : + triton::arch::ID_REG_RV32_X1 + ); + auto dst = triton::arch::OperandWrapper(ra); + auto& src = inst.operands[0]; + + /* Create semantics (jalr with 1 operand) */ + auto pc_ast = this->symbolicEngine->getOperandAst(pc); + auto node_dst = this->astCtxt->bvadd(pc_ast, this->astCtxt->bv(4, size)); + auto node_pc = this->symbolicEngine->getOperandAst(inst, src); + if (inst.operands.size() == 3) { // jalr with 3 operands semantics + dst = src; + src = inst.operands[1]; + auto& imm = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src); + auto op2 = this->symbolicEngine->getOperandAst(inst, imm); + + node_pc = this->astCtxt->bvadd(op1, op2); + } + node_pc = this->astCtxt->bvand( /* ignore last bit */ + node_pc, + this->astCtxt->bvshl(this->astCtxt->bv(-1, size), this->astCtxt->bv(1, size)) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node_dst, dst, "JALR operation ret addr"); + auto expr_pc = this->symbolicEngine->createSymbolicExpression(inst, node_pc, pc, "Program Counter"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(pc); + expr_pc->isTainted = this->taintEngine->isTainted(src); + + /* Create the path constraint */ + this->symbolicEngine->pushPathConstraint(inst, expr_pc); + } + + + void riscvSemantics::jalr_no_link_s(triton::arch::Instruction& inst) { // rd == x0 + auto pc = triton::arch::OperandWrapper(this->architecture->getProgramCounter()); + auto size = pc.getBitSize(); + auto ra = this->architecture->getRegister( + size == 64 ? + triton::arch::ID_REG_RV64_X1 : + triton::arch::ID_REG_RV32_X1 + ); + auto src = triton::arch::OperandWrapper(ra); + if (inst.operands.size()) { + src = inst.operands[0]; + } + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + node = this->astCtxt->bvand( /* ignore last bit */ + node, + this->astCtxt->bvshl(this->astCtxt->bv(-1, size), this->astCtxt->bv(1, size)) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, pc, "Program Counter"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(src); + + /* Create the path constraint */ + this->symbolicEngine->pushPathConstraint(inst, expr); + } + + + void riscvSemantics::lb_s(triton::arch::Instruction& inst) { + // x[rd] := M[x[rs] + offset][7:0] + auto& dst = inst.operands[0]; // rd + auto& src = inst.operands[1]; // rs - base, offset - disp + auto size = dst.getBitSize(); + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + node = this->astCtxt->sx(size - 8, node); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "LB operation - LOAD access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::lbu_s(triton::arch::Instruction& inst) { + // x[rd] := M[x[rs] + offset][7:0] + auto& dst = inst.operands[0]; // rd + auto& src = inst.operands[1]; // rs - base, offset - disp + auto size = dst.getBitSize(); + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + node = this->astCtxt->zx(size - 8, node); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "LBU operation - LOAD access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::ld_s(triton::arch::Instruction& inst) { /* 64-bit only */ + // x[rd] := M[x[rs] + offset][63:0] + auto& dst = inst.operands[0]; // rd + auto& src = inst.operands[1]; // rs - base, offset - disp + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "LD operation - LOAD access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::lh_s(triton::arch::Instruction& inst) { + // x[rd] := M[x[rs] + offset][15:0] + auto& dst = inst.operands[0]; // rd + auto& src = inst.operands[1]; // rs - base, offset - disp + auto size = dst.getBitSize(); + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + node = this->astCtxt->sx(size - 16, node); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "LH operation - LOAD access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::lhu_s(triton::arch::Instruction& inst) { + // x[rd] := M[x[rs] + offset][15:0] + auto& dst = inst.operands[0]; // rd + auto& src = inst.operands[1]; // rs - base, offset - disp + auto size = dst.getBitSize(); + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + node = this->astCtxt->zx(size - 16, node); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "LHU operation - LOAD access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::lui_s(triton::arch::Instruction& inst) { + // dst := (src_imm(_20) << 12) + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + + /* Create symbolic operands */ + auto imm = this->symbolicEngine->getOperandAst(inst, src); + + /* Create the semantics */ + auto node = this->astCtxt->concat(this->astCtxt->extract(19, 0, imm), this->astCtxt->bv(0, 12)); + if (dst.getBitSize() == 64) { /* extend to register size */ + node = this->astCtxt->sx(32, node); + } + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "LUI operation"); + + /* Spread taint */ + expr->isTainted = false; + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::lw_s(triton::arch::Instruction& inst) { + // x[rd] := M[x[rs] + offset][31:0] + auto& dst = inst.operands[0]; // rd + auto& src = inst.operands[1]; // rs1 - base, offset - disp + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + if (dst.getBitSize() == 64) { /* extend to register size */ + node = this->astCtxt->sx(32, node); + } + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "LW operation - LOAD access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::lwu_s(triton::arch::Instruction& inst) { /* 64-bit only */ + // x[rd] := M[x[rs] + offset][31:0] + auto& dst = inst.operands[0]; // rd + auto& src = inst.operands[1]; // rs1 - base, offset - disp + auto size = dst.getBitSize(); + + /* Create the semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + node = this->astCtxt->zx(32, node); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "LWU operation - LOAD access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::mul_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + + /* Create the semantics */ + auto node = this->astCtxt->bvmul(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "MUL operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::mulh_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + auto size = src2.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->astCtxt->sx(size, this->symbolicEngine->getOperandAst(inst, src1)); + auto op2 = this->astCtxt->sx(size, this->symbolicEngine->getOperandAst(inst, src2)); + + /* Create the semantics */ + auto node = this->astCtxt->extract(size * 2 - 1, size, this->astCtxt->bvmul(op1, op2)); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "MULH operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::mulhsu_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + auto size = src2.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->astCtxt->sx(size, this->symbolicEngine->getOperandAst(inst, src1)); + auto op2 = this->astCtxt->zx(size, this->symbolicEngine->getOperandAst(inst, src2)); + + /* Create the semantics */ + auto node = this->astCtxt->extract(size * 2 - 1, size, this->astCtxt->bvmul(op1, op2)); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "MULHSU operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::mulhu_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + auto size = src2.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->astCtxt->zx(size, this->symbolicEngine->getOperandAst(inst, src1)); + auto op2 = this->astCtxt->zx(size, this->symbolicEngine->getOperandAst(inst, src2)); + + /* Create the semantics */ + auto node = this->astCtxt->extract(size * 2 - 1, size, this->astCtxt->bvmul(op1, op2)); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "MULHU operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::mulw_s(triton::arch::Instruction& inst) { /* 64-bit only */ + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->astCtxt->extract(31, 0, this->symbolicEngine->getOperandAst(inst, src1)); + auto op2 = this->astCtxt->extract(31, 0, this->symbolicEngine->getOperandAst(inst, src2)); + + /* Create the semantics */ + auto node = this->astCtxt->sx(32, this->astCtxt->bvmul(op1, op2)); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "MULW operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::or_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + + /* Create the semantics */ + auto node = this->astCtxt->bvor(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "OR(I) operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::rem_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + + /* Create the semantics */ + auto node = this->astCtxt->ite( + this->astCtxt->equal(op2, this->astCtxt->bv(0, op2->getBitvectorSize())), + this->astCtxt->bv(0, dst.getBitSize()), + this->astCtxt->bvsrem(op1, op2) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "REM operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::remu_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + + /* Create the semantics */ + auto node = this->astCtxt->ite( + this->astCtxt->equal(op2, this->astCtxt->bv(0, op2->getBitvectorSize())), + this->astCtxt->bv(0, dst.getBitSize()), + this->astCtxt->bvurem(op1, op2) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "REMU operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::remuw_s(triton::arch::Instruction& inst) { /* 64-bit only */ + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->astCtxt->extract(31, 0, this->symbolicEngine->getOperandAst(inst, src1)); + auto op2 = this->astCtxt->extract(31, 0, this->symbolicEngine->getOperandAst(inst, src2)); + + /* Create the semantics */ + auto node = this->astCtxt->ite( + this->astCtxt->equal(op2, this->astCtxt->bv(0, op2->getBitvectorSize())), + this->astCtxt->bv(0, dst.getBitSize()), + this->astCtxt->sx(32, this->astCtxt->bvurem(op1, op2)) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "REMUW operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::remw_s(triton::arch::Instruction& inst) { /* 64-bit only */ + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->astCtxt->extract(31, 0, this->symbolicEngine->getOperandAst(inst, src1)); + auto op2 = this->astCtxt->extract(31, 0, this->symbolicEngine->getOperandAst(inst, src2)); + + /* Create the semantics */ + auto node = this->astCtxt->ite( + this->astCtxt->equal(op2, this->astCtxt->bv(0, op2->getBitvectorSize())), + this->astCtxt->bv(0, dst.getBitSize()), + this->astCtxt->sx(32, this->astCtxt->bvsrem(op1, op2)) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "REMW operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::sb_s(triton::arch::Instruction& inst) { + // M[x[rs1] + offset] := (x[rs2] & 0xff) + auto& src = inst.operands[0]; // rs2 + auto& dst = inst.operands[1]; // rs1 - base, offset - disp + + /* Create symbolic operands */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + node = this->astCtxt->extract(7, 0, node); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SB operation - STORE access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::sd_s(triton::arch::Instruction& inst) { /* 64-bit only */ + // M[x[rs1] + offset] := x[rs2] + auto& src = inst.operands[0]; // rs2 + auto& dst = inst.operands[1]; // rs1 - base, offset - disp + + /* Create symbolic operands */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SD operation - STORE access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::sh_s(triton::arch::Instruction& inst) { + // M[x[rs1] + offset] := (x[rs2] & 0xffff) + auto& src = inst.operands[0]; // rs2 + auto& dst = inst.operands[1]; // rs1 - base, offset - disp + + /* Create symbolic operands */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + node = this->astCtxt->extract(15, 0, node); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SH operation - STORE access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::sll_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + auto size = src2.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->astCtxt->bvand( + this->symbolicEngine->getOperandAst(inst, src2), + this->astCtxt->bv(0x1f, size) + ); + + /* Create the semantics */ + auto node = this->astCtxt->bvshl(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SLL(I) operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintUnion(src1, src2); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::sllw_s(triton::arch::Instruction& inst) { /* 64-bit only */ + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + auto size = src2.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->astCtxt->bvand( + this->symbolicEngine->getOperandAst(inst, src2), + this->astCtxt->bv(0x1f, size) + ); + + /* Create the semantics */ + auto node = this->astCtxt->bvshl( + this->astCtxt->sx(32, this->astCtxt->extract(31, 0, op1)), + op2 + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SLL(I)W operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintUnion(src1, src2); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::slt_s(triton::arch::Instruction& inst) { + /* Check for possible pseudo instructions + sltz rd, rs -- [slt rd, rs, x0] -- Set if < zero + sgtz rd, rs -- [slt rd, x0, rs] -- Set if > zero + */ + auto mnem = inst.getDisassembly(); + if (mnem[3] == 'z') { + if (mnem[1] == 'l') { slt_sltz_s(inst); } else { slt_sgtz_s(inst); } + } else { + slti_s(inst); + } + } + + + void riscvSemantics::slt_sgtz_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + auto size = dst.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src); + auto zero = this->astCtxt->bv(0, size); + + /* Create the semantics */ + auto node = this->astCtxt->ite(this->astCtxt->bvsgt(op1, zero), + this->astCtxt->bv(1, size), + zero + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SGTZ operation"); + + /* Set condition flag */ + if ((long long)op1->evaluate() > 0) + inst.setConditionTaken(true); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::slt_sltz_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + auto size = dst.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src); + auto zero = this->astCtxt->bv(0, size); + + /* Create the semantics */ + auto node = this->astCtxt->ite(this->astCtxt->bvslt(op1, zero), + this->astCtxt->bv(1, size), + zero + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SLTZ operation"); + + /* Set condition flag */ + if ((long long)op1->evaluate() < 0) + inst.setConditionTaken(true); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::slti_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + auto size = dst.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + + /* Create the semantics */ + auto node = this->astCtxt->ite(this->astCtxt->bvslt(op1, op2), + this->astCtxt->bv(1, size), + this->astCtxt->bv(0, size) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SLT(I) operation"); + + /* Set condition flag */ + if ((long long)(op2->evaluate() - op1->evaluate()) > 0) + inst.setConditionTaken(true); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::sltiu_seqz_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + auto size = dst.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src); + auto zero = this->astCtxt->bv(0, size); + + /* Create the semantics */ + auto node = this->astCtxt->ite(this->astCtxt->equal(op1, zero), + this->astCtxt->bv(1, size), + zero + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SEQZ operation"); + + /* Set condition flag */ + if (op1->evaluate() == 0) + inst.setConditionTaken(true); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::sltu_s(triton::arch::Instruction& inst) { + /* Check for possible pseudo instructions + seqz rd, rs -- [sltiu rd, rs, 1] -- Set if == zero + snez rd, rs -- [sltu rd, x0, rs] -- Set if != zero + */ + auto mnem = inst.getDisassembly(); + if (mnem[1] == 'e') { + sltiu_seqz_s(inst); + return; + } + if (mnem[1] == 'n') { + sltu_snez_s(inst); + return; + } + + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + auto size = dst.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + + /* Create the semantics */ + auto node = this->astCtxt->ite(this->astCtxt->bvult(op1, op2), + this->astCtxt->bv(1, size), + this->astCtxt->bv(0, size) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SLT(I)U operation"); + + /* Set condition flag */ + if (op2->evaluate() > op1->evaluate()) + inst.setConditionTaken(true); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::sltu_snez_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src = inst.operands[1]; + auto size = dst.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src); + auto zero = this->astCtxt->bv(0, size); + + /* Create the semantics */ + auto node = this->astCtxt->ite(this->astCtxt->equal(op1, zero), + zero, + this->astCtxt->bv(1, size) + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SNEZ operation"); + + /* Set condition flag */ + if (op1->evaluate() != 0) + inst.setConditionTaken(true); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::sra_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + auto size = src2.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->astCtxt->bvand( + this->symbolicEngine->getOperandAst(inst, src2), + this->astCtxt->bv(0x1f, size) + ); + + /* Create the semantics */ + auto node = this->astCtxt->bvashr(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SRA operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintUnion(src1, src2); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::sraw_s(triton::arch::Instruction& inst) { /* 64-bit only */ + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + auto size = src2.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->astCtxt->bvand( + this->symbolicEngine->getOperandAst(inst, src2), + this->astCtxt->bv(0x1f, size) + ); + + /* Create the semantics */ + auto node = this->astCtxt->bvashr( + this->astCtxt->sx(32, this->astCtxt->extract(31, 0, op1)), + op2 + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SRA(I)W operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintUnion(src1, src2); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::srl_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + auto size = src2.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->astCtxt->bvand( + this->symbolicEngine->getOperandAst(inst, src2), + this->astCtxt->bv(0x1f, size) + ); + + /* Create the semantics */ + auto node = this->astCtxt->bvlshr(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SRL(I) operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintUnion(src1, src2); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::srlw_s(triton::arch::Instruction& inst) { /* 64-bit only */ + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + auto size = src2.getBitSize(); + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->astCtxt->bvand( + this->symbolicEngine->getOperandAst(inst, src2), + this->astCtxt->bv(0x1f, size) + ); + + /* Create the semantics */ + auto node = this->astCtxt->bvlshr( + this->astCtxt->sx(32, this->astCtxt->extract(31, 0, op1)), + op2 + ); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SRL(I)W operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintUnion(src1, src2); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::sub_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto size = dst.getBitSize(); + bool fix_taint = false; + + /* Create symbolic operands and semantics */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto node = this->astCtxt->bvneg(op1); // neg pseudo instruction semantics + if (inst.operands.size() > 2) { + auto& src2 = inst.operands[2]; + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + node = this->astCtxt->bvsub(op1, op2); // sub semantics + fix_taint = this->taintEngine->isTainted(src2); + } + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SUB operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(src1) || fix_taint; + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::subw_s(triton::arch::Instruction& inst) { /* 64-bit only */ + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto size = dst.getBitSize(); + bool fix_taint = false; + + /* Create symbolic operands and semantics */ + auto op1 = this->astCtxt->extract(31, 0, this->symbolicEngine->getOperandAst(inst, src1)); + auto node = this->astCtxt->sx(32, this->astCtxt->bvneg(op1)); // negw pseudo instruction semantics + if (inst.operands.size() > 2) { + auto& src2 = inst.operands[2]; + auto op2 = this->astCtxt->extract(31, 0, this->symbolicEngine->getOperandAst(inst, src2)); + node = this->astCtxt->sx(32, this->astCtxt->bvsub(op1, op2)); // subw semantics + fix_taint = this->taintEngine->isTainted(src2); + } + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SUBW operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->isTainted(src1) || fix_taint; + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::sw_s(triton::arch::Instruction& inst) { + // M[x[rs1] + offset] := (x[rs2] & 0xffffffff) + auto& src = inst.operands[0]; // rs2 + auto& dst = inst.operands[1]; // rs1 - base, offset - disp + + /* Create symbolic operands and semantics */ + auto node = this->symbolicEngine->getOperandAst(inst, src); + if (src.getBitSize() == 64) { + node = this->astCtxt->extract(31, 0, node); + } + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "SW operation - STORE access"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->taintAssignment(dst, src); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::xor_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + auto& src2 = inst.operands[2]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + + /* Create the semantics */ + auto node = this->astCtxt->bvxor(op1, op2); + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "XOR operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1) | this->taintEngine->isTainted(src2)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + + void riscvSemantics::xori_s(triton::arch::Instruction& inst) { + auto& dst = inst.operands[0]; + auto& src1 = inst.operands[1]; + + /* Create symbolic operands */ + auto op1 = this->symbolicEngine->getOperandAst(inst, src1); + auto node = this->astCtxt->bvnot(op1); // not pseudo instruction semantics + + if (inst.operands.size() > 2) { + auto& src2 = inst.operands[2]; + auto op2 = this->symbolicEngine->getOperandAst(inst, src2); + node = this->astCtxt->bvxor(op1, op2); // xori semantics + } + + /* Create symbolic expression */ + auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "XORI operation"); + + /* Spread taint */ + expr->isTainted = this->taintEngine->setTaint(dst, this->taintEngine->isTainted(src1)); + + /* Update the symbolic control flow */ + this->controlFlow_s(inst); + } + + }; /* riscv namespace */ + }; /* arch namespace */ +}; /* triton namespace */ diff --git a/src/libtriton/arch/riscv/riscvSpecifications.cpp b/src/libtriton/arch/riscv/riscvSpecifications.cpp new file mode 100644 index 000000000..fef5285d6 --- /dev/null +++ b/src/libtriton/arch/riscv/riscvSpecifications.cpp @@ -0,0 +1,1233 @@ +//! \file +/* +** Copyright (C) - Triton +** +** This program is under the terms of the Apache License 2.0. +*/ + +#include + +#include +#include +#include +#include +#include + + + +namespace triton { + namespace arch { + namespace riscv { + + riscvSpecifications::riscvSpecifications(triton::arch::architecture_e arch) { + if (arch != triton::arch::ARCH_RV64 && arch != triton::arch::ARCH_RV32) + throw triton::exceptions::Architecture("riscvSpecifications::riscvSpecifications(): Invalid architecture."); + + if (arch == triton::arch::ARCH_RV64) { + // Fill id2reg and name2id with those available in riscv from spec + #define REG_SPEC(CS_UPPER_NAME, UPPER_NAME, LOWER_NAME, ABI_NAME, RISCV_UPPER, RISCV_LOWER, MUTABLE) \ + id2reg.emplace(ID_REG_RV64_##UPPER_NAME, \ + triton::arch::Register(triton::arch::ID_REG_RV64_##UPPER_NAME, \ + #LOWER_NAME, \ + triton::arch::ID_REG_RV64_##UPPER_NAME, \ + RISCV_UPPER, \ + RISCV_LOWER, \ + true) \ + ); \ + name2id.emplace(#LOWER_NAME, ID_REG_RV64_##UPPER_NAME); \ + name2id.emplace(#ABI_NAME, ID_REG_RV64_##UPPER_NAME); + // Handle register not available in capstone as normal registers + #define REG_SPEC_NO_CAPSTONE REG_SPEC + #include "triton/riscv64.spec" + } + else { // RV32 + // Fill id2reg and name2id with those available in riscv32 from spec + #define REG_SPEC(CS_UPPER_NAME, UPPER_NAME, LOWER_NAME, ABI_NAME, RISCV_UPPER, RISCV_LOWER, MUTABLE) \ + id2reg.emplace(ID_REG_RV32_##UPPER_NAME, \ + triton::arch::Register(triton::arch::ID_REG_RV32_##UPPER_NAME, \ + #LOWER_NAME, \ + triton::arch::ID_REG_RV32_##UPPER_NAME, \ + RISCV_UPPER, \ + RISCV_LOWER, \ + true) \ + ); \ + name2id.emplace(#LOWER_NAME, ID_REG_RV32_##UPPER_NAME); \ + name2id.emplace(#ABI_NAME, ID_REG_RV32_##UPPER_NAME); + // Handle register not available in capstone as normal registers + #define REG_SPEC_NO_CAPSTONE REG_SPEC + #include "triton/riscv32.spec" + } + } + + + triton::arch::register_e riscvSpecifications::capstoneRegisterToTritonRegister64(triton::uint32 id) const { + triton::arch::register_e tritonId = triton::arch::ID_REG_INVALID; + switch (id) { + // Convert registers from capstone value to triton value + #define REG_SPEC(CS_UPPER_NAME, UPPER_NAME, _1, _2, _3, _4, _5) \ + case triton::extlibs::capstone::RISCV_REG_##CS_UPPER_NAME: \ + tritonId = triton::arch::ID_REG_RV64_##UPPER_NAME; \ + break; + // Ignore registers not available in capstone + #define REG_SPEC_NO_CAPSTONE(_1, _2, _3, _4, _5, _6, _7) + #include "triton/riscv64.spec" + + default: + tritonId = triton::arch::ID_REG_INVALID; + break; + + } + return tritonId; + } + + + triton::arch::register_e riscvSpecifications::capstoneRegisterToTritonRegister32(triton::uint32 id) const { + triton::arch::register_e tritonId = triton::arch::ID_REG_INVALID; + switch (id) { + // Convert registers from capstone value to triton value + #define REG_SPEC(CS_UPPER_NAME, UPPER_NAME, _1, _2, _3, _4, _5) \ + case triton::extlibs::capstone::RISCV_REG_##CS_UPPER_NAME: \ + tritonId = triton::arch::ID_REG_RV32_##UPPER_NAME; \ + break; + // Ignore registers not available in capstone + #define REG_SPEC_NO_CAPSTONE(_1, _2, _3, _4, _5, _6, _7) + #include "triton/riscv32.spec" + + default: + tritonId = triton::arch::ID_REG_INVALID; + break; + + } + return tritonId; + } + + + triton::uint32 riscvSpecifications::capstoneInstructionToTritonInstruction(triton::uint32 id) const { + triton::uint32 tritonId = triton::arch::riscv::ID_INS_INVALID; + + switch (id) { + case triton::extlibs::capstone::RISCV_INS_INVALID: + tritonId = triton::arch::riscv::ID_INS_INVALID; + break; + + case triton::extlibs::capstone::RISCV_INS_ADD: + tritonId = triton::arch::riscv::ID_INS_ADD; + break; + + case triton::extlibs::capstone::RISCV_INS_ADDI: + tritonId = triton::arch::riscv::ID_INS_ADDI; + break; + + case triton::extlibs::capstone::RISCV_INS_ADDIW: + tritonId = triton::arch::riscv::ID_INS_ADDIW; + break; + + case triton::extlibs::capstone::RISCV_INS_ADDW: + tritonId = triton::arch::riscv::ID_INS_ADDW; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOADD_D: + tritonId = triton::arch::riscv::ID_INS_AMOADD_D; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOADD_D_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOADD_D_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOADD_D_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOADD_D_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOADD_D_RL: + tritonId = triton::arch::riscv::ID_INS_AMOADD_D_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOADD_W: + tritonId = triton::arch::riscv::ID_INS_AMOADD_W; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOADD_W_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOADD_W_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOADD_W_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOADD_W_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOADD_W_RL: + tritonId = triton::arch::riscv::ID_INS_AMOADD_W_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOAND_D: + tritonId = triton::arch::riscv::ID_INS_AMOAND_D; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOAND_D_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOAND_D_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOAND_D_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOAND_D_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOAND_D_RL: + tritonId = triton::arch::riscv::ID_INS_AMOAND_D_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOAND_W: + tritonId = triton::arch::riscv::ID_INS_AMOAND_W; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOAND_W_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOAND_W_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOAND_W_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOAND_W_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOAND_W_RL: + tritonId = triton::arch::riscv::ID_INS_AMOAND_W_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMAXU_D: + tritonId = triton::arch::riscv::ID_INS_AMOMAXU_D; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMAXU_D_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOMAXU_D_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMAXU_D_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOMAXU_D_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMAXU_D_RL: + tritonId = triton::arch::riscv::ID_INS_AMOMAXU_D_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMAXU_W: + tritonId = triton::arch::riscv::ID_INS_AMOMAXU_W; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMAXU_W_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOMAXU_W_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMAXU_W_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOMAXU_W_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMAXU_W_RL: + tritonId = triton::arch::riscv::ID_INS_AMOMAXU_W_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMAX_D: + tritonId = triton::arch::riscv::ID_INS_AMOMAX_D; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMAX_D_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOMAX_D_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMAX_D_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOMAX_D_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMAX_D_RL: + tritonId = triton::arch::riscv::ID_INS_AMOMAX_D_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMAX_W: + tritonId = triton::arch::riscv::ID_INS_AMOMAX_W; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMAX_W_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOMAX_W_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMAX_W_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOMAX_W_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMAX_W_RL: + tritonId = triton::arch::riscv::ID_INS_AMOMAX_W_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMINU_D: + tritonId = triton::arch::riscv::ID_INS_AMOMINU_D; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMINU_D_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOMINU_D_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMINU_D_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOMINU_D_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMINU_D_RL: + tritonId = triton::arch::riscv::ID_INS_AMOMINU_D_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMINU_W: + tritonId = triton::arch::riscv::ID_INS_AMOMINU_W; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMINU_W_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOMINU_W_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMINU_W_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOMINU_W_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMINU_W_RL: + tritonId = triton::arch::riscv::ID_INS_AMOMINU_W_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMIN_D: + tritonId = triton::arch::riscv::ID_INS_AMOMIN_D; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMIN_D_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOMIN_D_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMIN_D_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOMIN_D_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMIN_D_RL: + tritonId = triton::arch::riscv::ID_INS_AMOMIN_D_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMIN_W: + tritonId = triton::arch::riscv::ID_INS_AMOMIN_W; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMIN_W_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOMIN_W_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMIN_W_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOMIN_W_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOMIN_W_RL: + tritonId = triton::arch::riscv::ID_INS_AMOMIN_W_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOOR_D: + tritonId = triton::arch::riscv::ID_INS_AMOOR_D; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOOR_D_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOOR_D_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOOR_D_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOOR_D_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOOR_D_RL: + tritonId = triton::arch::riscv::ID_INS_AMOOR_D_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOOR_W: + tritonId = triton::arch::riscv::ID_INS_AMOOR_W; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOOR_W_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOOR_W_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOOR_W_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOOR_W_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOOR_W_RL: + tritonId = triton::arch::riscv::ID_INS_AMOOR_W_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOSWAP_D: + tritonId = triton::arch::riscv::ID_INS_AMOSWAP_D; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOSWAP_D_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOSWAP_D_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOSWAP_D_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOSWAP_D_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOSWAP_D_RL: + tritonId = triton::arch::riscv::ID_INS_AMOSWAP_D_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOSWAP_W: + tritonId = triton::arch::riscv::ID_INS_AMOSWAP_W; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOSWAP_W_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOSWAP_W_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOSWAP_W_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOSWAP_W_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOSWAP_W_RL: + tritonId = triton::arch::riscv::ID_INS_AMOSWAP_W_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOXOR_D: + tritonId = triton::arch::riscv::ID_INS_AMOXOR_D; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOXOR_D_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOXOR_D_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOXOR_D_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOXOR_D_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOXOR_D_RL: + tritonId = triton::arch::riscv::ID_INS_AMOXOR_D_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOXOR_W: + tritonId = triton::arch::riscv::ID_INS_AMOXOR_W; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOXOR_W_AQ: + tritonId = triton::arch::riscv::ID_INS_AMOXOR_W_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOXOR_W_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_AMOXOR_W_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AMOXOR_W_RL: + tritonId = triton::arch::riscv::ID_INS_AMOXOR_W_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_AND: + tritonId = triton::arch::riscv::ID_INS_AND; + break; + + case triton::extlibs::capstone::RISCV_INS_ANDI: + tritonId = triton::arch::riscv::ID_INS_ANDI; + break; + + case triton::extlibs::capstone::RISCV_INS_AUIPC: + tritonId = triton::arch::riscv::ID_INS_AUIPC; + break; + + case triton::extlibs::capstone::RISCV_INS_BEQ: + tritonId = triton::arch::riscv::ID_INS_BEQ; + break; + + case triton::extlibs::capstone::RISCV_INS_BGE: + tritonId = triton::arch::riscv::ID_INS_BGE; + break; + + case triton::extlibs::capstone::RISCV_INS_BGEU: + tritonId = triton::arch::riscv::ID_INS_BGEU; + break; + + case triton::extlibs::capstone::RISCV_INS_BLT: + tritonId = triton::arch::riscv::ID_INS_BLT; + break; + + case triton::extlibs::capstone::RISCV_INS_BLTU: + tritonId = triton::arch::riscv::ID_INS_BLTU; + break; + + case triton::extlibs::capstone::RISCV_INS_BNE: + tritonId = triton::arch::riscv::ID_INS_BNE; + break; + + case triton::extlibs::capstone::RISCV_INS_CSRRC: + tritonId = triton::arch::riscv::ID_INS_CSRRC; + break; + + case triton::extlibs::capstone::RISCV_INS_CSRRCI: + tritonId = triton::arch::riscv::ID_INS_CSRRCI; + break; + + case triton::extlibs::capstone::RISCV_INS_CSRRS: + tritonId = triton::arch::riscv::ID_INS_CSRRS; + break; + + case triton::extlibs::capstone::RISCV_INS_CSRRSI: + tritonId = triton::arch::riscv::ID_INS_CSRRSI; + break; + + case triton::extlibs::capstone::RISCV_INS_CSRRW: + tritonId = triton::arch::riscv::ID_INS_CSRRW; + break; + + case triton::extlibs::capstone::RISCV_INS_CSRRWI: + tritonId = triton::arch::riscv::ID_INS_CSRRWI; + break; + /* Compressed instructions */ + case triton::extlibs::capstone::RISCV_INS_C_ADD: + tritonId = triton::arch::riscv::ID_INS_C_ADD; + break; + + case triton::extlibs::capstone::RISCV_INS_C_ADDI: + tritonId = triton::arch::riscv::ID_INS_C_ADDI; + break; + + case triton::extlibs::capstone::RISCV_INS_C_ADDI16SP: + tritonId = triton::arch::riscv::ID_INS_C_ADDI16SP; + break; + + case triton::extlibs::capstone::RISCV_INS_C_ADDI4SPN: + tritonId = triton::arch::riscv::ID_INS_C_ADDI4SPN; + break; + + case triton::extlibs::capstone::RISCV_INS_C_ADDIW: + tritonId = triton::arch::riscv::ID_INS_C_ADDIW; + break; + + case triton::extlibs::capstone::RISCV_INS_C_ADDW: + tritonId = triton::arch::riscv::ID_INS_C_ADDW; + break; + + case triton::extlibs::capstone::RISCV_INS_C_AND: + tritonId = triton::arch::riscv::ID_INS_C_AND; + break; + + case triton::extlibs::capstone::RISCV_INS_C_ANDI: + tritonId = triton::arch::riscv::ID_INS_C_ANDI; + break; + + case triton::extlibs::capstone::RISCV_INS_C_BEQZ: + tritonId = triton::arch::riscv::ID_INS_C_BEQZ; + break; + + case triton::extlibs::capstone::RISCV_INS_C_BNEZ: + tritonId = triton::arch::riscv::ID_INS_C_BNEZ; + break; + + case triton::extlibs::capstone::RISCV_INS_C_EBREAK: + tritonId = triton::arch::riscv::ID_INS_C_EBREAK; + break; + + case triton::extlibs::capstone::RISCV_INS_C_FLD: + tritonId = triton::arch::riscv::ID_INS_C_FLD; + break; + + case triton::extlibs::capstone::RISCV_INS_C_FLDSP: + tritonId = triton::arch::riscv::ID_INS_C_FLDSP; + break; + + case triton::extlibs::capstone::RISCV_INS_C_FLW: + tritonId = triton::arch::riscv::ID_INS_C_FLW; + break; + + case triton::extlibs::capstone::RISCV_INS_C_FLWSP: + tritonId = triton::arch::riscv::ID_INS_C_FLWSP; + break; + + case triton::extlibs::capstone::RISCV_INS_C_FSD: + tritonId = triton::arch::riscv::ID_INS_C_FSD; + break; + + case triton::extlibs::capstone::RISCV_INS_C_FSDSP: + tritonId = triton::arch::riscv::ID_INS_C_FSDSP; + break; + + case triton::extlibs::capstone::RISCV_INS_C_FSW: + tritonId = triton::arch::riscv::ID_INS_C_FSW; + break; + + case triton::extlibs::capstone::RISCV_INS_C_FSWSP: + tritonId = triton::arch::riscv::ID_INS_C_FSWSP; + break; + + case triton::extlibs::capstone::RISCV_INS_C_J: + tritonId = triton::arch::riscv::ID_INS_C_J; + break; + + case triton::extlibs::capstone::RISCV_INS_C_JAL: + tritonId = triton::arch::riscv::ID_INS_C_JAL; + break; + + case triton::extlibs::capstone::RISCV_INS_C_JALR: + tritonId = triton::arch::riscv::ID_INS_C_JALR; + break; + + case triton::extlibs::capstone::RISCV_INS_C_JR: + tritonId = triton::arch::riscv::ID_INS_C_JR; + break; + + case triton::extlibs::capstone::RISCV_INS_C_LD: + tritonId = triton::arch::riscv::ID_INS_C_LD; + break; + + case triton::extlibs::capstone::RISCV_INS_C_LDSP: + tritonId = triton::arch::riscv::ID_INS_C_LDSP; + break; + + case triton::extlibs::capstone::RISCV_INS_C_LI: + tritonId = triton::arch::riscv::ID_INS_C_LI; + break; + + case triton::extlibs::capstone::RISCV_INS_C_LUI: + tritonId = triton::arch::riscv::ID_INS_C_LUI; + break; + + case triton::extlibs::capstone::RISCV_INS_C_LW: + tritonId = triton::arch::riscv::ID_INS_C_LW; + break; + + case triton::extlibs::capstone::RISCV_INS_C_LWSP: + tritonId = triton::arch::riscv::ID_INS_C_LWSP; + break; + + case triton::extlibs::capstone::RISCV_INS_C_MV: + tritonId = triton::arch::riscv::ID_INS_C_MV; + break; + + case triton::extlibs::capstone::RISCV_INS_C_NOP: + tritonId = triton::arch::riscv::ID_INS_C_NOP; + break; + + case triton::extlibs::capstone::RISCV_INS_C_OR: + tritonId = triton::arch::riscv::ID_INS_C_OR; + break; + + case triton::extlibs::capstone::RISCV_INS_C_SD: + tritonId = triton::arch::riscv::ID_INS_C_SD; + break; + + case triton::extlibs::capstone::RISCV_INS_C_SDSP: + tritonId = triton::arch::riscv::ID_INS_C_SDSP; + break; + + case triton::extlibs::capstone::RISCV_INS_C_SLLI: + tritonId = triton::arch::riscv::ID_INS_C_SLLI; + break; + + case triton::extlibs::capstone::RISCV_INS_C_SRAI: + tritonId = triton::arch::riscv::ID_INS_C_SRAI; + break; + + case triton::extlibs::capstone::RISCV_INS_C_SRLI: + tritonId = triton::arch::riscv::ID_INS_C_SRLI; + break; + + case triton::extlibs::capstone::RISCV_INS_C_SUB: + tritonId = triton::arch::riscv::ID_INS_C_SUB; + break; + + case triton::extlibs::capstone::RISCV_INS_C_SUBW: + tritonId = triton::arch::riscv::ID_INS_C_SUBW; + break; + + case triton::extlibs::capstone::RISCV_INS_C_SW: + tritonId = triton::arch::riscv::ID_INS_C_SW; + break; + + case triton::extlibs::capstone::RISCV_INS_C_SWSP: + tritonId = triton::arch::riscv::ID_INS_C_SWSP; + break; + + case triton::extlibs::capstone::RISCV_INS_C_UNIMP: + tritonId = triton::arch::riscv::ID_INS_C_UNIMP; + break; + + case triton::extlibs::capstone::RISCV_INS_C_XOR: + tritonId = triton::arch::riscv::ID_INS_C_XOR; + break; + /* End of compressed instructions */ + case triton::extlibs::capstone::RISCV_INS_DIV: + tritonId = triton::arch::riscv::ID_INS_DIV; + break; + + case triton::extlibs::capstone::RISCV_INS_DIVU: + tritonId = triton::arch::riscv::ID_INS_DIVU; + break; + + case triton::extlibs::capstone::RISCV_INS_DIVUW: + tritonId = triton::arch::riscv::ID_INS_DIVUW; + break; + + case triton::extlibs::capstone::RISCV_INS_DIVW: + tritonId = triton::arch::riscv::ID_INS_DIVW; + break; + + case triton::extlibs::capstone::RISCV_INS_EBREAK: + tritonId = triton::arch::riscv::ID_INS_EBREAK; + break; + + case triton::extlibs::capstone::RISCV_INS_ECALL: + tritonId = triton::arch::riscv::ID_INS_ECALL; + break; + + case triton::extlibs::capstone::RISCV_INS_FADD_D: + tritonId = triton::arch::riscv::ID_INS_FADD_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FADD_S: + tritonId = triton::arch::riscv::ID_INS_FADD_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FCLASS_D: + tritonId = triton::arch::riscv::ID_INS_FCLASS_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FCLASS_S: + tritonId = triton::arch::riscv::ID_INS_FCLASS_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_D_L: + tritonId = triton::arch::riscv::ID_INS_FCVT_D_L; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_D_LU: + tritonId = triton::arch::riscv::ID_INS_FCVT_D_LU; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_D_S: + tritonId = triton::arch::riscv::ID_INS_FCVT_D_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_D_W: + tritonId = triton::arch::riscv::ID_INS_FCVT_D_W; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_D_WU: + tritonId = triton::arch::riscv::ID_INS_FCVT_D_WU; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_LU_D: + tritonId = triton::arch::riscv::ID_INS_FCVT_LU_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_LU_S: + tritonId = triton::arch::riscv::ID_INS_FCVT_LU_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_L_D: + tritonId = triton::arch::riscv::ID_INS_FCVT_L_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_L_S: + tritonId = triton::arch::riscv::ID_INS_FCVT_L_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_S_D: + tritonId = triton::arch::riscv::ID_INS_FCVT_S_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_S_L: + tritonId = triton::arch::riscv::ID_INS_FCVT_S_L; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_S_LU: + tritonId = triton::arch::riscv::ID_INS_FCVT_S_LU; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_S_W: + tritonId = triton::arch::riscv::ID_INS_FCVT_S_W; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_S_WU: + tritonId = triton::arch::riscv::ID_INS_FCVT_S_WU; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_WU_D: + tritonId = triton::arch::riscv::ID_INS_FCVT_WU_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_WU_S: + tritonId = triton::arch::riscv::ID_INS_FCVT_WU_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_W_D: + tritonId = triton::arch::riscv::ID_INS_FCVT_W_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FCVT_W_S: + tritonId = triton::arch::riscv::ID_INS_FCVT_W_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FDIV_D: + tritonId = triton::arch::riscv::ID_INS_FDIV_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FDIV_S: + tritonId = triton::arch::riscv::ID_INS_FDIV_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FENCE: + tritonId = triton::arch::riscv::ID_INS_FENCE; + break; + + case triton::extlibs::capstone::RISCV_INS_FENCE_I: + tritonId = triton::arch::riscv::ID_INS_FENCE_I; + break; + + case triton::extlibs::capstone::RISCV_INS_FENCE_TSO: + tritonId = triton::arch::riscv::ID_INS_FENCE_TSO; + break; + + case triton::extlibs::capstone::RISCV_INS_FEQ_D: + tritonId = triton::arch::riscv::ID_INS_FEQ_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FEQ_S: + tritonId = triton::arch::riscv::ID_INS_FEQ_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FLD: + tritonId = triton::arch::riscv::ID_INS_FLD; + break; + + case triton::extlibs::capstone::RISCV_INS_FLE_D: + tritonId = triton::arch::riscv::ID_INS_FLE_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FLE_S: + tritonId = triton::arch::riscv::ID_INS_FLE_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FLT_D: + tritonId = triton::arch::riscv::ID_INS_FLT_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FLT_S: + tritonId = triton::arch::riscv::ID_INS_FLT_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FLW: + tritonId = triton::arch::riscv::ID_INS_FLW; + break; + + case triton::extlibs::capstone::RISCV_INS_FMADD_D: + tritonId = triton::arch::riscv::ID_INS_FMADD_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FMADD_S: + tritonId = triton::arch::riscv::ID_INS_FMADD_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FMAX_D: + tritonId = triton::arch::riscv::ID_INS_FMAX_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FMAX_S: + tritonId = triton::arch::riscv::ID_INS_FMAX_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FMIN_D: + tritonId = triton::arch::riscv::ID_INS_FMIN_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FMIN_S: + tritonId = triton::arch::riscv::ID_INS_FMIN_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FMSUB_D: + tritonId = triton::arch::riscv::ID_INS_FMSUB_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FMSUB_S: + tritonId = triton::arch::riscv::ID_INS_FMSUB_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FMUL_D: + tritonId = triton::arch::riscv::ID_INS_FMUL_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FMUL_S: + tritonId = triton::arch::riscv::ID_INS_FMUL_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FMV_D_X: + tritonId = triton::arch::riscv::ID_INS_FMV_D_X; + break; + + case triton::extlibs::capstone::RISCV_INS_FMV_W_X: + tritonId = triton::arch::riscv::ID_INS_FMV_W_X; + break; + + case triton::extlibs::capstone::RISCV_INS_FMV_X_D: + tritonId = triton::arch::riscv::ID_INS_FMV_X_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FMV_X_W: + tritonId = triton::arch::riscv::ID_INS_FMV_X_W; + break; + + case triton::extlibs::capstone::RISCV_INS_FNMADD_D: + tritonId = triton::arch::riscv::ID_INS_FNMADD_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FNMADD_S: + tritonId = triton::arch::riscv::ID_INS_FNMADD_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FNMSUB_D: + tritonId = triton::arch::riscv::ID_INS_FNMSUB_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FNMSUB_S: + tritonId = triton::arch::riscv::ID_INS_FNMSUB_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FSD: + tritonId = triton::arch::riscv::ID_INS_FSD; + break; + + case triton::extlibs::capstone::RISCV_INS_FSGNJN_D: + tritonId = triton::arch::riscv::ID_INS_FSGNJN_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FSGNJN_S: + tritonId = triton::arch::riscv::ID_INS_FSGNJN_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FSGNJX_D: + tritonId = triton::arch::riscv::ID_INS_FSGNJX_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FSGNJX_S: + tritonId = triton::arch::riscv::ID_INS_FSGNJX_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FSGNJ_D: + tritonId = triton::arch::riscv::ID_INS_FSGNJ_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FSGNJ_S: + tritonId = triton::arch::riscv::ID_INS_FSGNJ_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FSQRT_D: + tritonId = triton::arch::riscv::ID_INS_FSQRT_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FSQRT_S: + tritonId = triton::arch::riscv::ID_INS_FSQRT_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FSUB_D: + tritonId = triton::arch::riscv::ID_INS_FSUB_D; + break; + + case triton::extlibs::capstone::RISCV_INS_FSUB_S: + tritonId = triton::arch::riscv::ID_INS_FSUB_S; + break; + + case triton::extlibs::capstone::RISCV_INS_FSW: + tritonId = triton::arch::riscv::ID_INS_FSW; + break; + + case triton::extlibs::capstone::RISCV_INS_JAL: + tritonId = triton::arch::riscv::ID_INS_JAL; + break; + + case triton::extlibs::capstone::RISCV_INS_JALR: + tritonId = triton::arch::riscv::ID_INS_JALR; + break; + + case triton::extlibs::capstone::RISCV_INS_LB: + tritonId = triton::arch::riscv::ID_INS_LB; + break; + + case triton::extlibs::capstone::RISCV_INS_LBU: + tritonId = triton::arch::riscv::ID_INS_LBU; + break; + + case triton::extlibs::capstone::RISCV_INS_LD: + tritonId = triton::arch::riscv::ID_INS_LD; + break; + + case triton::extlibs::capstone::RISCV_INS_LH: + tritonId = triton::arch::riscv::ID_INS_LH; + break; + + case triton::extlibs::capstone::RISCV_INS_LHU: + tritonId = triton::arch::riscv::ID_INS_LHU; + break; + + case triton::extlibs::capstone::RISCV_INS_LR_D: + tritonId = triton::arch::riscv::ID_INS_LR_D; + break; + + case triton::extlibs::capstone::RISCV_INS_LR_D_AQ: + tritonId = triton::arch::riscv::ID_INS_LR_D_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_LR_D_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_LR_D_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_LR_D_RL: + tritonId = triton::arch::riscv::ID_INS_LR_D_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_LR_W: + tritonId = triton::arch::riscv::ID_INS_LR_W; + break; + + case triton::extlibs::capstone::RISCV_INS_LR_W_AQ: + tritonId = triton::arch::riscv::ID_INS_LR_W_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_LR_W_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_LR_W_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_LR_W_RL: + tritonId = triton::arch::riscv::ID_INS_LR_W_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_LUI: + tritonId = triton::arch::riscv::ID_INS_LUI; + break; + + case triton::extlibs::capstone::RISCV_INS_LW: + tritonId = triton::arch::riscv::ID_INS_LW; + break; + + case triton::extlibs::capstone::RISCV_INS_LWU: + tritonId = triton::arch::riscv::ID_INS_LWU; + break; + + case triton::extlibs::capstone::RISCV_INS_MRET: + tritonId = triton::arch::riscv::ID_INS_MRET; + break; + + case triton::extlibs::capstone::RISCV_INS_MUL: + tritonId = triton::arch::riscv::ID_INS_MUL; + break; + + case triton::extlibs::capstone::RISCV_INS_MULH: + tritonId = triton::arch::riscv::ID_INS_MULH; + break; + + case triton::extlibs::capstone::RISCV_INS_MULHSU: + tritonId = triton::arch::riscv::ID_INS_MULHSU; + break; + + case triton::extlibs::capstone::RISCV_INS_MULHU: + tritonId = triton::arch::riscv::ID_INS_MULHU; + break; + + case triton::extlibs::capstone::RISCV_INS_MULW: + tritonId = triton::arch::riscv::ID_INS_MULW; + break; + + case triton::extlibs::capstone::RISCV_INS_OR: + tritonId = triton::arch::riscv::ID_INS_OR; + break; + + case triton::extlibs::capstone::RISCV_INS_ORI: + tritonId = triton::arch::riscv::ID_INS_ORI; + break; + + case triton::extlibs::capstone::RISCV_INS_REM: + tritonId = triton::arch::riscv::ID_INS_REM; + break; + + case triton::extlibs::capstone::RISCV_INS_REMU: + tritonId = triton::arch::riscv::ID_INS_REMU; + break; + + case triton::extlibs::capstone::RISCV_INS_REMUW: + tritonId = triton::arch::riscv::ID_INS_REMUW; + break; + + case triton::extlibs::capstone::RISCV_INS_REMW: + tritonId = triton::arch::riscv::ID_INS_REMW; + break; + + case triton::extlibs::capstone::RISCV_INS_SB: + tritonId = triton::arch::riscv::ID_INS_SB; + break; + + case triton::extlibs::capstone::RISCV_INS_SC_D: + tritonId = triton::arch::riscv::ID_INS_SC_D; + break; + + case triton::extlibs::capstone::RISCV_INS_SC_D_AQ: + tritonId = triton::arch::riscv::ID_INS_SC_D_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_SC_D_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_SC_D_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_SC_D_RL: + tritonId = triton::arch::riscv::ID_INS_SC_D_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_SC_W: + tritonId = triton::arch::riscv::ID_INS_SC_W; + break; + + case triton::extlibs::capstone::RISCV_INS_SC_W_AQ: + tritonId = triton::arch::riscv::ID_INS_SC_W_AQ; + break; + + case triton::extlibs::capstone::RISCV_INS_SC_W_AQ_RL: + tritonId = triton::arch::riscv::ID_INS_SC_W_AQ_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_SC_W_RL: + tritonId = triton::arch::riscv::ID_INS_SC_W_RL; + break; + + case triton::extlibs::capstone::RISCV_INS_SD: + tritonId = triton::arch::riscv::ID_INS_SD; + break; + + case triton::extlibs::capstone::RISCV_INS_SFENCE_VMA: + tritonId = triton::arch::riscv::ID_INS_SFENCE_VMA; + break; + + case triton::extlibs::capstone::RISCV_INS_SH: + tritonId = triton::arch::riscv::ID_INS_SH; + break; + + case triton::extlibs::capstone::RISCV_INS_SLL: + tritonId = triton::arch::riscv::ID_INS_SLL; + break; + + case triton::extlibs::capstone::RISCV_INS_SLLI: + tritonId = triton::arch::riscv::ID_INS_SLLI; + break; + + case triton::extlibs::capstone::RISCV_INS_SLLIW: + tritonId = triton::arch::riscv::ID_INS_SLLIW; + break; + + case triton::extlibs::capstone::RISCV_INS_SLLW: + tritonId = triton::arch::riscv::ID_INS_SLLW; + break; + + case triton::extlibs::capstone::RISCV_INS_SLT: + tritonId = triton::arch::riscv::ID_INS_SLT; + break; + + case triton::extlibs::capstone::RISCV_INS_SLTI: + tritonId = triton::arch::riscv::ID_INS_SLTI; + break; + + case triton::extlibs::capstone::RISCV_INS_SLTIU: + tritonId = triton::arch::riscv::ID_INS_SLTIU; + break; + + case triton::extlibs::capstone::RISCV_INS_SLTU: + tritonId = triton::arch::riscv::ID_INS_SLTU; + break; + + case triton::extlibs::capstone::RISCV_INS_SRA: + tritonId = triton::arch::riscv::ID_INS_SRA; + break; + + case triton::extlibs::capstone::RISCV_INS_SRAI: + tritonId = triton::arch::riscv::ID_INS_SRAI; + break; + + case triton::extlibs::capstone::RISCV_INS_SRAIW: + tritonId = triton::arch::riscv::ID_INS_SRAIW; + break; + + case triton::extlibs::capstone::RISCV_INS_SRAW: + tritonId = triton::arch::riscv::ID_INS_SRAW; + break; + + case triton::extlibs::capstone::RISCV_INS_SRET: + tritonId = triton::arch::riscv::ID_INS_SRET; + break; + + case triton::extlibs::capstone::RISCV_INS_SRL: + tritonId = triton::arch::riscv::ID_INS_SRL; + break; + + case triton::extlibs::capstone::RISCV_INS_SRLI: + tritonId = triton::arch::riscv::ID_INS_SRLI; + break; + + case triton::extlibs::capstone::RISCV_INS_SRLIW: + tritonId = triton::arch::riscv::ID_INS_SRLIW; + break; + + case triton::extlibs::capstone::RISCV_INS_SRLW: + tritonId = triton::arch::riscv::ID_INS_SRLW; + break; + + case triton::extlibs::capstone::RISCV_INS_SUB: + tritonId = triton::arch::riscv::ID_INS_SUB; + break; + + case triton::extlibs::capstone::RISCV_INS_SUBW: + tritonId = triton::arch::riscv::ID_INS_SUBW; + break; + + case triton::extlibs::capstone::RISCV_INS_SW: + tritonId = triton::arch::riscv::ID_INS_SW; + break; + + case triton::extlibs::capstone::RISCV_INS_UNIMP: + tritonId = ID_INS_UNIMP; + break; + + case triton::extlibs::capstone::RISCV_INS_URET: + tritonId = ID_INS_URET; + break; + + case triton::extlibs::capstone::RISCV_INS_WFI: + tritonId = ID_INS_WFI; + break; + + case triton::extlibs::capstone::RISCV_INS_XOR: + tritonId = ID_INS_XOR; + break; + + case triton::extlibs::capstone::RISCV_INS_XORI: + tritonId = ID_INS_XORI; + break; + default: + tritonId = triton::arch::riscv::ID_INS_INVALID; + break; + } + + return tritonId; + } + + + triton::uint32 riscvSpecifications::getMemoryOperandSpecialSize(triton::uint32 id) const { + switch (id) { + case ID_INS_LB: + case ID_INS_LBU: + case ID_INS_SB: + return 1; + case ID_INS_LH: + case ID_INS_LHU: + case ID_INS_SH: + return 2; + case ID_INS_LW: + case ID_INS_LWU: + case ID_INS_SW: + return 4; + case ID_INS_LD: + case ID_INS_SD: + return 8; + default: + return 0; + } + } + + }; /* riscv namespace */ + }; /* arch namespace */ +}; /* triton namespace */ diff --git a/src/libtriton/bindings/python/namespaces/initArchNamespace.cpp b/src/libtriton/bindings/python/namespaces/initArchNamespace.cpp index 2f7a9b644..800b9727a 100644 --- a/src/libtriton/bindings/python/namespaces/initArchNamespace.cpp +++ b/src/libtriton/bindings/python/namespaces/initArchNamespace.cpp @@ -29,6 +29,8 @@ The ARCH namespace contains all kinds of architecture supported by Triton. - **ARCH.ARM32** - **ARCH.X86** - **ARCH.X86_64** +- **ARCH.RV64** +- **ARCH.RV32** */ @@ -43,6 +45,8 @@ namespace triton { xPyDict_SetItemString(archDict, "ARM32", PyLong_FromUint32(triton::arch::ARCH_ARM32)); xPyDict_SetItemString(archDict, "X86", PyLong_FromUint32(triton::arch::ARCH_X86)); xPyDict_SetItemString(archDict, "X86_64", PyLong_FromUint32(triton::arch::ARCH_X86_64)); + xPyDict_SetItemString(archDict, "RV64", PyLong_FromUint32(triton::arch::ARCH_RV64)); + xPyDict_SetItemString(archDict, "RV32", PyLong_FromUint32(triton::arch::ARCH_RV32)); } }; /* python namespace */ diff --git a/src/libtriton/includes/triton/archEnums.hpp b/src/libtriton/includes/triton/archEnums.hpp index 2ec4f07ce..c6629c929 100644 --- a/src/libtriton/includes/triton/archEnums.hpp +++ b/src/libtriton/includes/triton/archEnums.hpp @@ -33,6 +33,8 @@ namespace triton { ARCH_INVALID = 0, /*!< Invalid architecture. */ ARCH_AARCH64, /*!< AArch64 architecture. */ ARCH_ARM32, /*!< ARM32 architecture. */ + ARCH_RV32, /*!< RISCV32 architecture. */ + ARCH_RV64, /*!< RISCV64 architecture. */ ARCH_X86, /*!< X86 architecture. */ ARCH_X86_64, /*!< X86_64 architecture. */ }; @@ -80,6 +82,16 @@ namespace triton { #define REG_SPEC_NO_CAPSTONE REG_SPEC #include "triton/arm32.spec" + #define REG_SPEC(_1, UPPER_NAME, _2, _3, _4, _5, _6) \ + ID_REG_RV64_##UPPER_NAME, + #define REG_SPEC_NO_CAPSTONE REG_SPEC + #include "triton/riscv64.spec" + + #define REG_SPEC(_1, UPPER_NAME, _2, _3, _4, _5, _6) \ + ID_REG_RV32_##UPPER_NAME, + #define REG_SPEC_NO_CAPSTONE REG_SPEC + #include "triton/riscv32.spec" + /* Must be the last item */ ID_REG_LAST_ITEM //!< must be the last item }; @@ -193,6 +205,56 @@ namespace triton { /*! @} End of arm namespace */ }; + + //! The riscv namespace + namespace riscv { + /*! + * \ingroup arch + * \addtogroup riscv + * @{ + */ + + //! Groups of RISCV instructions. */ + enum insn_group_e { + ID_GRP_INVALID = 0, //!< invalid + /* Generic groups */ + ID_GRP_JUMP, //!< JUMP (all jump instructions: conditional+direct+indirect jumps) + ID_GRP_CALL, //!< CALL + ID_GRP_RET, //!< RET + ID_GRP_INT, //!< all interrupt instructions (int+syscall) + ID_GRP_IRET, //!< all interrupt return instructions + ID_GRP_PRIVILEGE, //!< all privileged instructions + ID_GRP_BRANCH_RELATIVE, //!< all relative branching instructions + /* Architecture-specific groups */ + ID_GRP_ISRV32, + ID_GRP_ISRV64, + ID_GRP_HASSTDEXTA, + ID_GRP_HASSTDEXTC, + ID_GRP_HASSTDEXTD, + ID_GRP_HASSTDEXTF, + ID_GRP_HASSTDEXTM, + /* + ID_GRP_ISRVA, + ID_GRP_ISRVC, + ID_GRP_ISRVD, + ID_GRP_ISRVCD, + ID_GRP_ISRVF, + ID_GRP_ISRV32C, + ID_GRP_ISRV32CF, + ID_GRP_ISRVM, + ID_GRP_ISRV64A, + ID_GRP_ISRV64C, + ID_GRP_ISRV64D, + ID_GRP_ISRV64F, + ID_GRP_ISRV64M, + */ + + /* Must be the last item */ + ID_GRP_ENDING //!< must be the last item + }; + + /*! @} End of riscv namespace */ + }; /*! @} End of arch namespace */ }; /*! @} End of triton namespace */ diff --git a/src/libtriton/includes/triton/externalLibs.hpp b/src/libtriton/includes/triton/externalLibs.hpp index a4bb87be7..49d699468 100644 --- a/src/libtriton/includes/triton/externalLibs.hpp +++ b/src/libtriton/includes/triton/externalLibs.hpp @@ -32,6 +32,7 @@ namespace triton { #include #include #include + #include #include /*! @} End of capstone namespace */ }; diff --git a/src/libtriton/includes/triton/irBuilder.hpp b/src/libtriton/includes/triton/irBuilder.hpp index 6032db50d..45d21f6f6 100644 --- a/src/libtriton/includes/triton/irBuilder.hpp +++ b/src/libtriton/includes/triton/irBuilder.hpp @@ -79,6 +79,9 @@ namespace triton { //! x86 ISA builder. triton::arch::SemanticsInterface* x86Isa; + //! RISCV ISA builder. + triton::arch::SemanticsInterface* riscvIsa; + public: //! Constructor. TRITON_EXPORT IrBuilder(triton::arch::Architecture* architecture, diff --git a/src/libtriton/includes/triton/riscv32.spec b/src/libtriton/includes/triton/riscv32.spec new file mode 100644 index 000000000..808d122a3 --- /dev/null +++ b/src/libtriton/includes/triton/riscv32.spec @@ -0,0 +1,89 @@ +#pragma warning(disable:4067) + +#if not (defined REG_SPEC || defined REG_SPEC_NO_CAPSTONE) +#error REG_SPEC have to be specified before including specs +#endif + +#define TT_MUTABLE_REG true +#define TT_IMMUTABLE_REG false + +// REG_SPEC(CS_UPPER_NAME, UPPER_NAME, LOWER_NAME, ABI_NAME, RISCV32_UPPER, RISCV32_LOWER, RISCV_PARENT, MUTABLE) + +// Thirty-two 32-bit general-purpose registers +REG_SPEC(X0, X0, x0, zero, triton::bitsize::dword-1, 0, TT_IMMUTABLE_REG) // x0 / zero +REG_SPEC(X1, X1, x1, ra, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x1 / ra +REG_SPEC(SP, SP, x2, sp, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x2 / sp +REG_SPEC(X3, X3, x3, gp, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x3 / gp +REG_SPEC(X4, X4, x4, tp, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x4 / tp +REG_SPEC(X5, X5, x5, t0, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x5 / t0 or lr +REG_SPEC(X6, X6, x6, t1, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x6 / t1 +REG_SPEC(X7, X7, x7, t2, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x7 / t2 +REG_SPEC(X8, X8, x8, s0, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x8 / s0 or fp +REG_SPEC(X9, X9, x9, s1, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x9 / s1 +REG_SPEC(X10, X10, x10, a0, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x10 / a0 +REG_SPEC(X11, X11, x11, a1, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x11 / a1 +REG_SPEC(X12, X12, x12, a2, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x12 / a2 +REG_SPEC(X13, X13, x13, a3, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x13 / a3 +REG_SPEC(X14, X14, x14, a4, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x14 / a4 +REG_SPEC(X15, X15, x15, a5, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x15 / a5 +REG_SPEC(X16, X16, x16, a6, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x16 / a6 +REG_SPEC(X17, X17, x17, a7, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x17 / a7 +REG_SPEC(X18, X18, x18, s2, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x18 / s2 +REG_SPEC(X19, X19, x19, s3, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x19 / s3 +REG_SPEC(X20, X20, x20, s4, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x20 / s4 +REG_SPEC(X21, X21, x21, s5, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x21 / s5 +REG_SPEC(X22, X22, x22, s6, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x22 / s6 +REG_SPEC(X23, X23, x23, s7, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x23 / s7 +REG_SPEC(X24, X24, x24, s8, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x24 / s8 +REG_SPEC(X25, X25, x25, s9, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x25 / s9 +REG_SPEC(X26, X26, x26, s10, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x26 / s10 +REG_SPEC(X27, X27, x27, s11, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x27 / s11 +REG_SPEC(X28, X28, x28, t3, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x28 / t3 +REG_SPEC(X29, X29, x29, t4, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x29 / t4 +REG_SPEC(X30, X30, x30, t5, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x30 / t5 +REG_SPEC(X31, X31, x31, t6, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // x31 / t6 + +// 32-bit program counter register +REG_SPEC_NO_CAPSTONE(PC, PC, pc, pc, triton::bitsize::dword-1, 0, TT_MUTABLE_REG) // PC + +// Thirty-two 32-bit floating-point registers +REG_SPEC(F0_32, F0, f0, ft0, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f0 +REG_SPEC(F1_32, F1, f1, ft1, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f1 +REG_SPEC(F2_32, F2, f2, ft2, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f2 +REG_SPEC(F3_32, F3, f3, ft3, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f3 +REG_SPEC(F4_32, F4, f4, ft4, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f4 +REG_SPEC(F5_32, F5, f5, ft5, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f5 +REG_SPEC(F6_32, F6, f6, ft6, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f6 +REG_SPEC(F7_32, F7, f7, ft7, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f7 +REG_SPEC(F8_32, F8, f8, fs0, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f8 +REG_SPEC(F9_32, F9, f9, fs1, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f9 +REG_SPEC(F10_32, F10, f10, fa0, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f10 +REG_SPEC(F11_32, F11, f11, fa1, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f11 +REG_SPEC(F12_32, F12, f12, fa2, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f12 +REG_SPEC(F13_32, F13, f13, fa3, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f13 +REG_SPEC(F14_32, F14, f14, fa4, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f14 +REG_SPEC(F15_32, F15, f15, fa5, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f15 +REG_SPEC(F16_32, F16, f16, fa6, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f16 +REG_SPEC(F17_32, F17, f17, fa7, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f17 +REG_SPEC(F18_32, F18, f18, fs2, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f18 +REG_SPEC(F19_32, F19, f19, fs3, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f19 +REG_SPEC(F20_32, F20, f20, fs4, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f20 +REG_SPEC(F21_32, F21, f21, fs5, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f21 +REG_SPEC(F22_32, F22, f22, fs6, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f22 +REG_SPEC(F23_32, F23, f23, fs7, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f23 +REG_SPEC(F24_32, F24, f24, fs8, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f24 +REG_SPEC(F25_32, F25, f25, fs9, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f25 +REG_SPEC(F26_32, F26, f26, fs10, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f26 +REG_SPEC(F27_32, F27, f27, fs11, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f27 +REG_SPEC(F28_32, F28, f28, ft8, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f28 +REG_SPEC(F29_32, F29, f29, ft9, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f29 +REG_SPEC(F30_32, F30, f30, ft10, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f30 +REG_SPEC(F31_32, F31, f31, ft11, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // f31 + +#undef REG_SPEC +#undef REG_SPEC_NO_CAPSTONE +#undef SYS_REG_SPEC +#undef TT_IMMUTABLE_REG +#undef TT_MUTABLE_REG + +#pragma warning(default:4067) diff --git a/src/libtriton/includes/triton/riscv32Cpu.hpp b/src/libtriton/includes/triton/riscv32Cpu.hpp new file mode 100644 index 000000000..82afe63ba --- /dev/null +++ b/src/libtriton/includes/triton/riscv32Cpu.hpp @@ -0,0 +1,284 @@ +//! \file +/* +** Copyright (C) - Triton +** +** This program is under the terms of the Apache License 2.0. +*/ + +#ifndef TRITON_RISCV32CPU_HPP +#define TRITON_RISCV32CPU_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +//! The Triton namespace +namespace triton { +/*! + * \addtogroup triton + * @{ + */ + + //! The Architecture namespace + namespace arch { + /*! + * \ingroup triton + * \addtogroup arch + * @{ + */ + + //! The riscv namespace + namespace riscv { + /*! + * \ingroup arch + * \addtogroup riscv + * @{ + */ + + //! \class riscv32Cpu + /*! \brief This class is used to describe the RV32 spec. */ + class riscv32Cpu : public CpuInterface, public riscvSpecifications { + + static const triton::arch::register_e pcId = triton::arch::ID_REG_RV32_PC; + static const triton::arch::register_e spId = triton::arch::ID_REG_RV32_SP; + + private: + //! Callbacks API + triton::callbacks::Callbacks* callbacks; + + //! Capstone context + std::size_t handle; + + //! Copies a riscv32Cpu class. + void copy(const riscv32Cpu& other); + + //! Initializes the disassembler + void disassInit(void); + + protected: + /*! \brief map of address -> concrete value + * + * \details + * + * **item1**: memory address
+ * **item2**: concrete value + */ + std::unordered_map> memory; + + //! Concrete value of x0 + triton::uint8 x0[triton::size::dword]; + //! Concrete value of x1 + triton::uint8 x1[triton::size::dword]; + //! Concrete value of sp + triton::uint8 sp[triton::size::dword]; + //! Concrete value of x3 + triton::uint8 x3[triton::size::dword]; + //! Concrete value of x4 + triton::uint8 x4[triton::size::dword]; + //! Concrete value of x5 + triton::uint8 x5[triton::size::dword]; + //! Concrete value of x6 + triton::uint8 x6[triton::size::dword]; + //! Concrete value of x7 + triton::uint8 x7[triton::size::dword]; + //! Concrete value of x8 + triton::uint8 x8[triton::size::dword]; + //! Concrete value of x9 + triton::uint8 x9[triton::size::dword]; + //! Concrete value of x10 + triton::uint8 x10[triton::size::dword]; + //! Concrete value of x11 + triton::uint8 x11[triton::size::dword]; + //! Concrete value of x12 + triton::uint8 x12[triton::size::dword]; + //! Concrete value of x13 + triton::uint8 x13[triton::size::dword]; + //! Concrete value of x14 + triton::uint8 x14[triton::size::dword]; + //! Concrete value of x15 + triton::uint8 x15[triton::size::dword]; + //! Concrete value of x16 + triton::uint8 x16[triton::size::dword]; + //! Concrete value of x17 + triton::uint8 x17[triton::size::dword]; + //! Concrete value of x18 + triton::uint8 x18[triton::size::dword]; + //! Concrete value of x19 + triton::uint8 x19[triton::size::dword]; + //! Concrete value of x20 + triton::uint8 x20[triton::size::dword]; + //! Concrete value of x21 + triton::uint8 x21[triton::size::dword]; + //! Concrete value of x22 + triton::uint8 x22[triton::size::dword]; + //! Concrete value of x23 + triton::uint8 x23[triton::size::dword]; + //! Concrete value of x24 + triton::uint8 x24[triton::size::dword]; + //! Concrete value of x25 + triton::uint8 x25[triton::size::dword]; + //! Concrete value of x26 + triton::uint8 x26[triton::size::dword]; + //! Concrete value of x27 + triton::uint8 x27[triton::size::dword]; + //! Concrete value of x28 + triton::uint8 x28[triton::size::dword]; + //! Concrete value of x29 + triton::uint8 x29[triton::size::dword]; + //! Concrete value of x30 + triton::uint8 x30[triton::size::dword]; + //! Concrete value of x31 + triton::uint8 x31[triton::size::dword]; + //! Concrete value of f0 + triton::uint8 f0[triton::size::qword]; + //! Concrete value of f1 + triton::uint8 f1[triton::size::qword]; + //! Concrete value of f2 + triton::uint8 f2[triton::size::qword]; + //! Concrete value of f3 + triton::uint8 f3[triton::size::qword]; + //! Concrete value of f4 + triton::uint8 f4[triton::size::qword]; + //! Concrete value of f5 + triton::uint8 f5[triton::size::qword]; + //! Concrete value of f6 + triton::uint8 f6[triton::size::qword]; + //! Concrete value of f7 + triton::uint8 f7[triton::size::qword]; + //! Concrete value of f8 + triton::uint8 f8[triton::size::qword]; + //! Concrete value of f9 + triton::uint8 f9[triton::size::qword]; + //! Concrete value of f10 + triton::uint8 f10[triton::size::qword]; + //! Concrete value of f11 + triton::uint8 f11[triton::size::qword]; + //! Concrete value of f12 + triton::uint8 f12[triton::size::qword]; + //! Concrete value of f13 + triton::uint8 f13[triton::size::qword]; + //! Concrete value of f14 + triton::uint8 f14[triton::size::qword]; + //! Concrete value of f15 + triton::uint8 f15[triton::size::qword]; + //! Concrete value of f16 + triton::uint8 f16[triton::size::qword]; + //! Concrete value of f17 + triton::uint8 f17[triton::size::qword]; + //! Concrete value of f18 + triton::uint8 f18[triton::size::qword]; + //! Concrete value of f19 + triton::uint8 f19[triton::size::qword]; + //! Concrete value of f20 + triton::uint8 f20[triton::size::qword]; + //! Concrete value of f21 + triton::uint8 f21[triton::size::qword]; + //! Concrete value of f22 + triton::uint8 f22[triton::size::qword]; + //! Concrete value of f23 + triton::uint8 f23[triton::size::qword]; + //! Concrete value of f24 + triton::uint8 f24[triton::size::qword]; + //! Concrete value of f25 + triton::uint8 f25[triton::size::qword]; + //! Concrete value of f26 + triton::uint8 f26[triton::size::qword]; + //! Concrete value of f27 + triton::uint8 f27[triton::size::qword]; + //! Concrete value of f28 + triton::uint8 f28[triton::size::qword]; + //! Concrete value of f29 + triton::uint8 f29[triton::size::qword]; + //! Concrete value of f30 + triton::uint8 f30[triton::size::qword]; + //! Concrete value of f31 + triton::uint8 f31[triton::size::qword]; + //! Concrete value of pc + triton::uint8 pc[triton::size::dword]; + + //! System registers + #define SYS_REG_SPEC(_, LOWER_NAME, _2, _3, _4, _5, _6) \ + triton::uint8 LOWER_NAME[triton::size::qword]; + #define REG_SPEC(_1, _2, _3, _4, _5, _6, _7) + #define REG_SPEC_NO_CAPSTONE(_1, _2, _3, _4, _5, _6, _7) + #include "triton/riscv32.spec" + + public: + //! Constructor. + TRITON_EXPORT riscv32Cpu(triton::callbacks::Callbacks* callbacks=nullptr); + + //! Constructor + TRITON_EXPORT riscv32Cpu(const riscv32Cpu& other); + + //! Destructor. + TRITON_EXPORT virtual ~riscv32Cpu(); + + //! Copies a riscv32Cpu class. + TRITON_EXPORT riscv32Cpu& operator=(const riscv32Cpu& other); + + //! Returns true if regId is a GRP. + TRITON_EXPORT bool isGPR(triton::arch::register_e regId) const; + + //! Returns true if regId is a FPU register. + TRITON_EXPORT bool isFPU(triton::arch::register_e regId) const; + + /* Virtual pure inheritance ================================================= */ + TRITON_EXPORT bool isFlag(triton::arch::register_e regId) const; + TRITON_EXPORT bool isRegister(triton::arch::register_e regId) const; + TRITON_EXPORT bool isRegisterValid(triton::arch::register_e regId) const; + TRITON_EXPORT bool isThumb(void) const; + TRITON_EXPORT bool isMemoryExclusive(const triton::arch::MemoryAccess& mem) const; + TRITON_EXPORT const std::unordered_map& getAllRegisters(void) const; + TRITON_EXPORT const std::unordered_map>& getConcreteMemory(void) const; + TRITON_EXPORT const triton::arch::Register& getParentRegister(const triton::arch::Register& reg) const; + TRITON_EXPORT const triton::arch::Register& getParentRegister(triton::arch::register_e id) const; + TRITON_EXPORT const triton::arch::Register& getProgramCounter(void) const; + TRITON_EXPORT const triton::arch::Register& getRegister(triton::arch::register_e id) const; + TRITON_EXPORT const triton::arch::Register& getRegister(const std::string& name) const; + TRITON_EXPORT const triton::arch::Register& getStackPointer(void) const; + TRITON_EXPORT std::set getParentRegisters(void) const; + TRITON_EXPORT std::vector getConcreteMemoryAreaValue(triton::uint64 baseAddr, triton::usize size, bool execCallbacks=true) const; + TRITON_EXPORT triton::arch::endianness_e getEndianness(void) const; + TRITON_EXPORT triton::uint32 numberOfRegisters(void) const; + TRITON_EXPORT triton::uint32 gprBitSize(void) const; + TRITON_EXPORT triton::uint32 gprSize(void) const; + TRITON_EXPORT triton::uint512 getConcreteMemoryValue(const triton::arch::MemoryAccess& mem, bool execCallbacks=true) const; + TRITON_EXPORT triton::uint512 getConcreteRegisterValue(const triton::arch::Register& reg, bool execCallbacks=true) const; + TRITON_EXPORT triton::uint8 getConcreteMemoryValue(triton::uint64 addr, bool execCallbacks=true) const; + TRITON_EXPORT void clear(void); + TRITON_EXPORT void disassembly(triton::arch::Instruction& inst); + TRITON_EXPORT void setConcreteMemoryAreaValue(triton::uint64 baseAddr, const std::vector& values, bool execCallbacks=true); + TRITON_EXPORT void setConcreteMemoryAreaValue(triton::uint64 baseAddr, const void* area, triton::usize size, bool execCallbacks=true); + TRITON_EXPORT void setConcreteMemoryValue(const triton::arch::MemoryAccess& mem, const triton::uint512& value, bool execCallbacks=true); + TRITON_EXPORT void setConcreteMemoryValue(triton::uint64 addr, triton::uint8 value, bool execCallbacks=true); + TRITON_EXPORT void setConcreteRegisterValue(const triton::arch::Register& reg, const triton::uint512& value, bool execCallbacks=true); + TRITON_EXPORT void setThumb(bool state); + TRITON_EXPORT void setMemoryExclusiveTag(const triton::arch::MemoryAccess& mem, bool tag); + TRITON_EXPORT bool isConcreteMemoryValueDefined(const triton::arch::MemoryAccess& mem) const; + TRITON_EXPORT bool isConcreteMemoryValueDefined(triton::uint64 baseAddr, triton::usize size=1) const; + TRITON_EXPORT void clearConcreteMemoryValue(const triton::arch::MemoryAccess& mem); + TRITON_EXPORT void clearConcreteMemoryValue(triton::uint64 baseAddr, triton::usize size=1); + /* End of virtual pure inheritance ========================================== */ + }; + + /*! @} End of riscv namespace */ + }; + /*! @} End of arch namespace */ + }; +/*! @} End of triton namespace */ +}; + +#endif /* TRITON_RISCV32CPU_HPP */ diff --git a/src/libtriton/includes/triton/riscv64.spec b/src/libtriton/includes/triton/riscv64.spec new file mode 100644 index 000000000..d742262b5 --- /dev/null +++ b/src/libtriton/includes/triton/riscv64.spec @@ -0,0 +1,89 @@ +#pragma warning(disable:4067) + +#if not (defined REG_SPEC || defined REG_SPEC_NO_CAPSTONE) +#error REG_SPEC have to be specified before including specs +#endif + +#define TT_MUTABLE_REG true +#define TT_IMMUTABLE_REG false + +// REG_SPEC(CS_UPPER_NAME, UPPER_NAME, LOWER_NAME, ABI_NAME, RISCV64_UPPER, RISCV64_LOWER, MUTABLE) + +// Thirty-two 64-bit general-purpose registers +REG_SPEC(X0, X0, x0, zero, triton::bitsize::qword-1, 0, TT_IMMUTABLE_REG) // x0 / zero +REG_SPEC(X1, X1, x1, ra, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x1 / ra +REG_SPEC(SP, SP, x2, sp, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x2 / sp +REG_SPEC(X3, X3, x3, gp, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x3 / gp +REG_SPEC(X4, X4, x4, tp, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x4 / tp +REG_SPEC(X5, X5, x5, t0, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x5 / t0 or lr +REG_SPEC(X6, X6, x6, t1, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x6 / t1 +REG_SPEC(X7, X7, x7, t2, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x7 / t2 +REG_SPEC(X8, X8, x8, s0, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x8 / s0 or fp +REG_SPEC(X9, X9, x9, s1, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x9 / s1 +REG_SPEC(X10, X10, x10, a0, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x10 / a0 +REG_SPEC(X11, X11, x11, a1, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x11 / a1 +REG_SPEC(X12, X12, x12, a2, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x12 / a2 +REG_SPEC(X13, X13, x13, a3, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x13 / a3 +REG_SPEC(X14, X14, x14, a4, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x14 / a4 +REG_SPEC(X15, X15, x15, a5, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x15 / a5 +REG_SPEC(X16, X16, x16, a6, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x16 / a6 +REG_SPEC(X17, X17, x17, a7, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x17 / a7 +REG_SPEC(X18, X18, x18, s2, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x18 / s2 +REG_SPEC(X19, X19, x19, s3, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x19 / s3 +REG_SPEC(X20, X20, x20, s4, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x20 / s4 +REG_SPEC(X21, X21, x21, s5, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x21 / s5 +REG_SPEC(X22, X22, x22, s6, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x22 / s6 +REG_SPEC(X23, X23, x23, s7, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x23 / s7 +REG_SPEC(X24, X24, x24, s8, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x24 / s8 +REG_SPEC(X25, X25, x25, s9, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x25 / s9 +REG_SPEC(X26, X26, x26, s10, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x26 / s10 +REG_SPEC(X27, X27, x27, s11, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x27 / s11 +REG_SPEC(X28, X28, x28, t3, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x28 / t3 +REG_SPEC(X29, X29, x29, t4, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x29 / t4 +REG_SPEC(X30, X30, x30, t5, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x30 / t5 +REG_SPEC(X31, X31, x31, t6, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // x31 / t6 + +// Program counter register +REG_SPEC_NO_CAPSTONE(PC, PC, pc, pc, triton::bitsize::qword-1, 0, TT_MUTABLE_REG) // PC + +// Thirty-two 64-bit floating-point registers +REG_SPEC(F0_64, F0, f0, ft0, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f0 +REG_SPEC(F1_64, F1, f1, ft1, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f1 +REG_SPEC(F2_64, F2, f2, ft2, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f2 +REG_SPEC(F3_64, F3, f3, ft3, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f3 +REG_SPEC(F4_64, F4, f4, ft4, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f4 +REG_SPEC(F5_64, F5, f5, ft5, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f5 +REG_SPEC(F6_64, F6, f6, ft6, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f6 +REG_SPEC(F7_64, F7, f7, ft7, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f7 +REG_SPEC(F8_64, F8, f8, fs0, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f8 +REG_SPEC(F9_64, F9, f9, fs1, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f9 +REG_SPEC(F10_64, F10, f10, fa0, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f10 +REG_SPEC(F11_64, F11, f11, fa1, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f11 +REG_SPEC(F12_64, F12, f12, fa2, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f12 +REG_SPEC(F13_64, F13, f13, fa3, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f13 +REG_SPEC(F14_64, F14, f14, fa4, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f14 +REG_SPEC(F15_64, F15, f15, fa5, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f15 +REG_SPEC(F16_64, F16, f16, fa6, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f16 +REG_SPEC(F17_64, F17, f17, fa7, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f17 +REG_SPEC(F18_64, F18, f18, fs2, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f18 +REG_SPEC(F19_64, F19, f19, fs3, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f19 +REG_SPEC(F20_64, F20, f20, fs4, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f20 +REG_SPEC(F21_64, F21, f21, fs5, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f21 +REG_SPEC(F22_64, F22, f22, fs6, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f22 +REG_SPEC(F23_64, F23, f23, fs7, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f23 +REG_SPEC(F24_64, F24, f24, fs8, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f24 +REG_SPEC(F25_64, F25, f25, fs9, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f25 +REG_SPEC(F26_64, F26, f26, fs10, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f26 +REG_SPEC(F27_64, F27, f27, fs11, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f27 +REG_SPEC(F28_64, F28, f28, ft8, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f28 +REG_SPEC(F29_64, F29, f29, ft9, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f29 +REG_SPEC(F30_64, F30, f30, ft10, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f30 +REG_SPEC(F31_64, F31, f31, ft11, triton::bitsize::dqword-1, 0, TT_MUTABLE_REG) // f31 + +#undef REG_SPEC +#undef REG_SPEC_NO_CAPSTONE +#undef SYS_REG_SPEC +#undef TT_IMMUTABLE_REG +#undef TT_MUTABLE_REG + +#pragma warning(default:4067) diff --git a/src/libtriton/includes/triton/riscv64Cpu.hpp b/src/libtriton/includes/triton/riscv64Cpu.hpp new file mode 100644 index 000000000..7914d7263 --- /dev/null +++ b/src/libtriton/includes/triton/riscv64Cpu.hpp @@ -0,0 +1,284 @@ +//! \file +/* +** Copyright (C) - Triton +** +** This program is under the terms of the Apache License 2.0. +*/ + +#ifndef TRITON_RISCV64CPU_HPP +#define TRITON_RISCV64CPU_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +//! The Triton namespace +namespace triton { +/*! + * \addtogroup triton + * @{ + */ + + //! The Architecture namespace + namespace arch { + /*! + * \ingroup triton + * \addtogroup arch + * @{ + */ + + //! The riscv namespace + namespace riscv { + /*! + * \ingroup arch + * \addtogroup riscv + * @{ + */ + + //! \class riscv64Cpu + /*! \brief This class is used to describe the RV64 spec. */ + class riscv64Cpu : public CpuInterface, public riscvSpecifications { + + static const triton::arch::register_e pcId = triton::arch::ID_REG_RV64_PC; + static const triton::arch::register_e spId = triton::arch::ID_REG_RV64_SP; + + private: + //! Callbacks API + triton::callbacks::Callbacks* callbacks; + + //! Capstone context + std::size_t handle; + + //! Copies a riscv64Cpu class. + void copy(const riscv64Cpu& other); + + //! Initializes the disassembler + void disassInit(void); + + protected: + /*! \brief map of address -> concrete value + * + * \details + * + * **item1**: memory address
+ * **item2**: concrete value + */ + std::unordered_map> memory; + + //! Concrete value of x0 + triton::uint8 x0[triton::size::qword]; + //! Concrete value of x1 + triton::uint8 x1[triton::size::qword]; + //! Concrete value of sp + triton::uint8 sp[triton::size::qword]; + //! Concrete value of x3 + triton::uint8 x3[triton::size::qword]; + //! Concrete value of x4 + triton::uint8 x4[triton::size::qword]; + //! Concrete value of x5 + triton::uint8 x5[triton::size::qword]; + //! Concrete value of x6 + triton::uint8 x6[triton::size::qword]; + //! Concrete value of x7 + triton::uint8 x7[triton::size::qword]; + //! Concrete value of x8 + triton::uint8 x8[triton::size::qword]; + //! Concrete value of x9 + triton::uint8 x9[triton::size::qword]; + //! Concrete value of x10 + triton::uint8 x10[triton::size::qword]; + //! Concrete value of x11 + triton::uint8 x11[triton::size::qword]; + //! Concrete value of x12 + triton::uint8 x12[triton::size::qword]; + //! Concrete value of x13 + triton::uint8 x13[triton::size::qword]; + //! Concrete value of x14 + triton::uint8 x14[triton::size::qword]; + //! Concrete value of x15 + triton::uint8 x15[triton::size::qword]; + //! Concrete value of x16 + triton::uint8 x16[triton::size::qword]; + //! Concrete value of x17 + triton::uint8 x17[triton::size::qword]; + //! Concrete value of x18 + triton::uint8 x18[triton::size::qword]; + //! Concrete value of x19 + triton::uint8 x19[triton::size::qword]; + //! Concrete value of x20 + triton::uint8 x20[triton::size::qword]; + //! Concrete value of x21 + triton::uint8 x21[triton::size::qword]; + //! Concrete value of x22 + triton::uint8 x22[triton::size::qword]; + //! Concrete value of x23 + triton::uint8 x23[triton::size::qword]; + //! Concrete value of x24 + triton::uint8 x24[triton::size::qword]; + //! Concrete value of x25 + triton::uint8 x25[triton::size::qword]; + //! Concrete value of x26 + triton::uint8 x26[triton::size::qword]; + //! Concrete value of x27 + triton::uint8 x27[triton::size::qword]; + //! Concrete value of x28 + triton::uint8 x28[triton::size::qword]; + //! Concrete value of x29 + triton::uint8 x29[triton::size::qword]; + //! Concrete value of x30 + triton::uint8 x30[triton::size::qword]; + //! Concrete value of x31 + triton::uint8 x31[triton::size::qword]; + //! Concrete value of f0 + triton::uint8 f0[triton::size::dqword]; + //! Concrete value of f1 + triton::uint8 f1[triton::size::dqword]; + //! Concrete value of f2 + triton::uint8 f2[triton::size::dqword]; + //! Concrete value of f3 + triton::uint8 f3[triton::size::dqword]; + //! Concrete value of f4 + triton::uint8 f4[triton::size::dqword]; + //! Concrete value of f5 + triton::uint8 f5[triton::size::dqword]; + //! Concrete value of f6 + triton::uint8 f6[triton::size::dqword]; + //! Concrete value of f7 + triton::uint8 f7[triton::size::dqword]; + //! Concrete value of f8 + triton::uint8 f8[triton::size::dqword]; + //! Concrete value of f9 + triton::uint8 f9[triton::size::dqword]; + //! Concrete value of f10 + triton::uint8 f10[triton::size::dqword]; + //! Concrete value of f11 + triton::uint8 f11[triton::size::dqword]; + //! Concrete value of f12 + triton::uint8 f12[triton::size::dqword]; + //! Concrete value of f13 + triton::uint8 f13[triton::size::dqword]; + //! Concrete value of f14 + triton::uint8 f14[triton::size::dqword]; + //! Concrete value of f15 + triton::uint8 f15[triton::size::dqword]; + //! Concrete value of f16 + triton::uint8 f16[triton::size::dqword]; + //! Concrete value of f17 + triton::uint8 f17[triton::size::dqword]; + //! Concrete value of f18 + triton::uint8 f18[triton::size::dqword]; + //! Concrete value of f19 + triton::uint8 f19[triton::size::dqword]; + //! Concrete value of f20 + triton::uint8 f20[triton::size::dqword]; + //! Concrete value of f21 + triton::uint8 f21[triton::size::dqword]; + //! Concrete value of f22 + triton::uint8 f22[triton::size::dqword]; + //! Concrete value of f23 + triton::uint8 f23[triton::size::dqword]; + //! Concrete value of f24 + triton::uint8 f24[triton::size::dqword]; + //! Concrete value of f25 + triton::uint8 f25[triton::size::dqword]; + //! Concrete value of f26 + triton::uint8 f26[triton::size::dqword]; + //! Concrete value of f27 + triton::uint8 f27[triton::size::dqword]; + //! Concrete value of f28 + triton::uint8 f28[triton::size::dqword]; + //! Concrete value of f29 + triton::uint8 f29[triton::size::dqword]; + //! Concrete value of f30 + triton::uint8 f30[triton::size::dqword]; + //! Concrete value of f31 + triton::uint8 f31[triton::size::dqword]; + //! Concrete value of pc + triton::uint8 pc[triton::size::qword]; + + //! System registers + #define SYS_REG_SPEC(_, LOWER_NAME, _2, _3, _4, _5, _6) \ + triton::uint8 LOWER_NAME[triton::size::qword]; + #define REG_SPEC(_1, _2, _3, _4, _5, _6, _7) + #define REG_SPEC_NO_CAPSTONE(_1, _2, _3, _4, _5, _6, _7) + #include "triton/riscv64.spec" + + public: + //! Constructor. + TRITON_EXPORT riscv64Cpu(triton::callbacks::Callbacks* callbacks=nullptr); + + //! Constructor + TRITON_EXPORT riscv64Cpu(const riscv64Cpu& other); + + //! Destructor. + TRITON_EXPORT virtual ~riscv64Cpu(); + + //! Copies a riscv64Cpu class. + TRITON_EXPORT riscv64Cpu& operator=(const riscv64Cpu& other); + + //! Returns true if regId is a GRP. + TRITON_EXPORT bool isGPR(triton::arch::register_e regId) const; + + //! Returns true if regId is a FPU register. + TRITON_EXPORT bool isFPU(triton::arch::register_e regId) const; + + /* Virtual pure inheritance ================================================= */ + TRITON_EXPORT bool isFlag(triton::arch::register_e regId) const; + TRITON_EXPORT bool isRegister(triton::arch::register_e regId) const; + TRITON_EXPORT bool isRegisterValid(triton::arch::register_e regId) const; + TRITON_EXPORT bool isThumb(void) const; + TRITON_EXPORT bool isMemoryExclusive(const triton::arch::MemoryAccess& mem) const; + TRITON_EXPORT const std::unordered_map& getAllRegisters(void) const; + TRITON_EXPORT const std::unordered_map>& getConcreteMemory(void) const; + TRITON_EXPORT const triton::arch::Register& getParentRegister(const triton::arch::Register& reg) const; + TRITON_EXPORT const triton::arch::Register& getParentRegister(triton::arch::register_e id) const; + TRITON_EXPORT const triton::arch::Register& getProgramCounter(void) const; + TRITON_EXPORT const triton::arch::Register& getRegister(triton::arch::register_e id) const; + TRITON_EXPORT const triton::arch::Register& getRegister(const std::string& name) const; + TRITON_EXPORT const triton::arch::Register& getStackPointer(void) const; + TRITON_EXPORT std::set getParentRegisters(void) const; + TRITON_EXPORT std::vector getConcreteMemoryAreaValue(triton::uint64 baseAddr, triton::usize size, bool execCallbacks=true) const; + TRITON_EXPORT triton::arch::endianness_e getEndianness(void) const; + TRITON_EXPORT triton::uint32 numberOfRegisters(void) const; + TRITON_EXPORT triton::uint32 gprBitSize(void) const; + TRITON_EXPORT triton::uint32 gprSize(void) const; + TRITON_EXPORT triton::uint512 getConcreteMemoryValue(const triton::arch::MemoryAccess& mem, bool execCallbacks=true) const; + TRITON_EXPORT triton::uint512 getConcreteRegisterValue(const triton::arch::Register& reg, bool execCallbacks=true) const; + TRITON_EXPORT triton::uint8 getConcreteMemoryValue(triton::uint64 addr, bool execCallbacks=true) const; + TRITON_EXPORT void clear(void); + TRITON_EXPORT void disassembly(triton::arch::Instruction& inst); + TRITON_EXPORT void setConcreteMemoryAreaValue(triton::uint64 baseAddr, const std::vector& values, bool execCallbacks=true); + TRITON_EXPORT void setConcreteMemoryAreaValue(triton::uint64 baseAddr, const void* area, triton::usize size, bool execCallbacks=true); + TRITON_EXPORT void setConcreteMemoryValue(const triton::arch::MemoryAccess& mem, const triton::uint512& value, bool execCallbacks=true); + TRITON_EXPORT void setConcreteMemoryValue(triton::uint64 addr, triton::uint8 value, bool execCallbacks=true); + TRITON_EXPORT void setConcreteRegisterValue(const triton::arch::Register& reg, const triton::uint512& value, bool execCallbacks=true); + TRITON_EXPORT void setThumb(bool state); + TRITON_EXPORT void setMemoryExclusiveTag(const triton::arch::MemoryAccess& mem, bool tag); + TRITON_EXPORT bool isConcreteMemoryValueDefined(const triton::arch::MemoryAccess& mem) const; + TRITON_EXPORT bool isConcreteMemoryValueDefined(triton::uint64 baseAddr, triton::usize size=1) const; + TRITON_EXPORT void clearConcreteMemoryValue(const triton::arch::MemoryAccess& mem); + TRITON_EXPORT void clearConcreteMemoryValue(triton::uint64 baseAddr, triton::usize size=1); + /* End of virtual pure inheritance ========================================== */ + }; + + /*! @} End of riscv namespace */ + }; + /*! @} End of arch namespace */ + }; +/*! @} End of triton namespace */ +}; + +#endif /* TRITON_RISCV64CPU_HPP */ diff --git a/src/libtriton/includes/triton/riscvSemantics.hpp b/src/libtriton/includes/triton/riscvSemantics.hpp new file mode 100644 index 000000000..05a0c5cf5 --- /dev/null +++ b/src/libtriton/includes/triton/riscvSemantics.hpp @@ -0,0 +1,388 @@ +//! \file +/* +** Copyright (C) - Triton +** +** This program is under the terms of the Apache License 2.0. +*/ + +#ifndef TRITON_RISCVSEMANTICS_H +#define TRITON_RISCVSEMANTICS_H + +#include +#include +#include +#include +#include +#include +#include +#include + + + +//! The Triton namespace +namespace triton { +/*! + * \addtogroup triton + * @{ + */ + + //! The Architecture namespace + namespace arch { + /*! + * \ingroup triton + * \addtogroup arch + * @{ + */ + + //! The x86 namespace + namespace riscv { + /*! + * \ingroup arch + * \addtogroup riscv + * @{ + */ + + /*! \class riscvSemantics + \brief The RISCV ISA semantics. */ + class riscvSemantics : public SemanticsInterface { + private: + //! Architecture API + triton::arch::Architecture* architecture; + + //! Symbolic Engine API + triton::engines::symbolic::SymbolicEngine* symbolicEngine; + + //! Taint Engine API + triton::engines::taint::TaintEngine* taintEngine; + + //! The Modes API + triton::modes::SharedModes modes; + + //! The AST Context API + triton::ast::SharedAstContext astCtxt; + + //! Exception status + triton::arch::exception_e exception; + + public: + //! Constructor. + TRITON_EXPORT riscvSemantics(triton::arch::Architecture* architecture, + triton::engines::symbolic::SymbolicEngine* symbolicEngine, + triton::engines::taint::TaintEngine* taintEngine, + const triton::modes::SharedModes& modes, + const triton::ast::SharedAstContext& astCtxt); + + //! Builds the semantics of the instruction. Returns `triton::arch::NO_FAULT` if succeed. + TRITON_EXPORT triton::arch::exception_e buildSemantics(triton::arch::Instruction& inst); + + private: + //! Control flow semantics. Used to represent PC. + void controlFlow_s(triton::arch::Instruction& inst); + + //! The ADD semantics. + void add_s(triton::arch::Instruction& inst); + + //! The ADDI semantics. + void addi_s(triton::arch::Instruction& inst); + + //! The MV (ADDI pseudo instruction) semantics. + void addi_mv_s(triton::arch::Instruction& inst); + + //! The ADDIW semantics. + void addiw_s(triton::arch::Instruction& inst); + + //! The ADDW semantics. + void addw_s(triton::arch::Instruction& inst); + + //! The AND semantics. + void and_s(triton::arch::Instruction& inst); + + //! The ANDI semantics. + void andi_s(triton::arch::Instruction& inst); + + //! The AUIPC semantics. + void auipc_s(triton::arch::Instruction& inst); + + //! The BEQ semantics. + void beq_s(triton::arch::Instruction& inst); + + //! The BGE semantics. + void bge_s(triton::arch::Instruction& inst); + + //! The BGEU semantics. + void bgeu_s(triton::arch::Instruction& inst); + + //! The BLT semantics. + void blt_s(triton::arch::Instruction& inst); + + //! The BLTU semantics. + void bltu_s(triton::arch::Instruction& inst); + + //! The BNE semantics. + void bne_s(triton::arch::Instruction& inst); + + //! The compressed ADD semantics. + void c_add_s(triton::arch::Instruction& inst); + + //! The compressed ADDI semantics. + void c_addi_s(triton::arch::Instruction& inst); + + //! The compressed ADDI16SP semantics. + void c_addi16sp_s(triton::arch::Instruction& inst); + + //! The compressed ADDI4SPN semantics. + void c_addi4spn_s(triton::arch::Instruction& inst); + + //! The compressed ADDIW semantics. + void c_addiw_s(triton::arch::Instruction& inst); + + //! The compressed ADDW semantics. + void c_addw_s(triton::arch::Instruction& inst); + + //! The compressed AND semantics. + void c_and_s(triton::arch::Instruction& inst); + + //! The compressed ANDI semantics. + void c_andi_s(triton::arch::Instruction& inst); + + //! The compressed BEQZ semantics. + void c_beqz_s(triton::arch::Instruction& inst); + + //! The compressed BNEZ semantics. + void c_bnez_s(triton::arch::Instruction& inst); + + //! The compressed JAL semantics. + void c_jal_s(triton::arch::Instruction& inst); + + //! The compressed JALR semantics. + void c_jalr_s(triton::arch::Instruction& inst); + + //! The compressed LD semantics. + void c_ld_s(triton::arch::Instruction& inst); + + //! The compressed LDSP semantics. + void c_ldsp_s(triton::arch::Instruction& inst); + + //! The compressed LI semantics. + void c_li_s(triton::arch::Instruction& inst); + + //! The compressed LW semantics. + void c_lw_s(triton::arch::Instruction& inst); + + //! The compressed LWSP semantics. + void c_lwsp_s(triton::arch::Instruction& inst); + + //! The compressed MV semantics. + void c_mv_s(triton::arch::Instruction& inst); + + //! The compressed NOP semantics. + void c_nop_s(triton::arch::Instruction& inst); + + //! The compressed OR semantics. + void c_or_s(triton::arch::Instruction& inst); + + //! The compressed SD semantics. + void c_sd_s(triton::arch::Instruction& inst); + + //! The compressed SDSP semantics. + void c_sdsp_s(triton::arch::Instruction& inst); + + //! The compressed SLLI semantics. + void c_slli_s(triton::arch::Instruction& inst); + + //! The compressed SRAI semantics. + void c_srai_s(triton::arch::Instruction& inst); + + //! The compressed SRLI semantics. + void c_srli_s(triton::arch::Instruction& inst); + + //! The compressed SUB semantics. + void c_sub_s(triton::arch::Instruction& inst); + + //! The compressed SUBW semantics. + void c_subw_s(triton::arch::Instruction& inst); + + //! The compressed SW semantics. + void c_sw_s(triton::arch::Instruction& inst); + + //! The compressed SWSP semantics. + void c_swsp_s(triton::arch::Instruction& inst); + + //! The compressed XOR semantics. + void c_xor_s(triton::arch::Instruction& inst); + + //! The DIV semantics. + void div_s(triton::arch::Instruction& inst); + + //! The DIVU semantics. + void divu_s(triton::arch::Instruction& inst); + + //! The DIVUW semantics. + void divuw_s(triton::arch::Instruction& inst); + + //! The DIVW semantics. + void divw_s(triton::arch::Instruction& inst); + + //! The JAL semantics. + void jal_s(triton::arch::Instruction& inst); + + //! The J (JAL pseudo instruction) semantics. + void jal_j_s(triton::arch::Instruction& inst); + + //! The JALR semantics. + void jalr_s(triton::arch::Instruction& inst); + + //! The RET/JR (JALR pseudo instruction) semantics. + void jalr_no_link_s(triton::arch::Instruction& inst); + + //! The LB semantics. + void lb_s(triton::arch::Instruction& inst); + + //! The LBU semantics. + void lbu_s(triton::arch::Instruction& inst); + + //! The LD semantics. + void ld_s(triton::arch::Instruction& inst); + + //! The LH semantics. + void lh_s(triton::arch::Instruction& inst); + + //! The LHU semantics. + void lhu_s(triton::arch::Instruction& inst); + + //! The LUI semantics. + void lui_s(triton::arch::Instruction& inst); + + //! The LW semantics. + void lw_s(triton::arch::Instruction& inst); + + //! The LWU semantics. + void lwu_s(triton::arch::Instruction& inst); + + //! The MUL semantics. + void mul_s(triton::arch::Instruction& inst); + + //! The MULH semantics. + void mulh_s(triton::arch::Instruction& inst); + + //! The MULHSU semantics. + void mulhsu_s(triton::arch::Instruction& inst); + + //! The MULHU semantics. + void mulhu_s(triton::arch::Instruction& inst); + + //! The MULW semantics. + void mulw_s(triton::arch::Instruction& inst); + + //! The OR semantics. + void or_s(triton::arch::Instruction& inst); + + //! The ORI semantics. + void ori_s(triton::arch::Instruction& inst); + + //! The REM semantics. + void rem_s(triton::arch::Instruction& inst); + + //! The REMU semantics. + void remu_s(triton::arch::Instruction& inst); + + //! The REMUW semantics. + void remuw_s(triton::arch::Instruction& inst); + + //! The REMW semantics. + void remw_s(triton::arch::Instruction& inst); + + //! The SB semantics. + void sb_s(triton::arch::Instruction& inst); + + //! The SD semantics. + void sd_s(triton::arch::Instruction& inst); + + //! The SH semantics. + void sh_s(triton::arch::Instruction& inst); + + //! The SLL semantics. + void sll_s(triton::arch::Instruction& inst); + + //! The SLLI semantics. + void slli_s(triton::arch::Instruction& inst); + + //! The SLLIW semantics. + void slliw_s(triton::arch::Instruction& inst); + + //! The SLLW semantics. + void sllw_s(triton::arch::Instruction& inst); + + //! The SLT semantics. + void slt_s(triton::arch::Instruction& inst); + + //! The SGTZ (SLT pseudo instruction) semantics. + void slt_sgtz_s(triton::arch::Instruction& inst); + + //! The SLTZ (SLT pseudo instruction) semantics. + void slt_sltz_s(triton::arch::Instruction& inst); + + //! The SLTI semantics. + void slti_s(triton::arch::Instruction& inst); + + //! The SLTIU semantics. + void sltiu_s(triton::arch::Instruction& inst); + + //! The The SEQZ (SLTIU pseudo instruction) semantics. + void sltiu_seqz_s(triton::arch::Instruction& inst); + + //! The SLTU semantics. + void sltu_s(triton::arch::Instruction& inst); + + //! The The SNEZ (SLTU pseudo instruction) semantics. + void sltu_snez_s(triton::arch::Instruction& inst); + + //! The SRA semantics. + void sra_s(triton::arch::Instruction& inst); + + //! The SRAI semantics. + void srai_s(triton::arch::Instruction& inst); + + //! The SRAIW semantics. + void sraiw_s(triton::arch::Instruction& inst); + + //! The SRAW semantics. + void sraw_s(triton::arch::Instruction& inst); + + //! The SRL semantics. + void srl_s(triton::arch::Instruction& inst); + + //! The SRLI semantics. + void srli_s(triton::arch::Instruction& inst); + + //! The SRLIW semantics. + void srliw_s(triton::arch::Instruction& inst); + + //! The SRLW semantics. + void srlw_s(triton::arch::Instruction& inst); + + //! The SUB semantics. + void sub_s(triton::arch::Instruction& inst); + + //! The SUBW semantics. + void subw_s(triton::arch::Instruction& inst); + + //! The SW semantics. + void sw_s(triton::arch::Instruction& inst); + + //! The XOR semantics. + void xor_s(triton::arch::Instruction& inst); + + //! The XORI semantics. + void xori_s(triton::arch::Instruction& inst); + }; + + /*! @} End of riscv namespace */ + }; + /*! @} End of arch namespace */ + }; +/*! @} End of triton namespace */ +}; + +#endif /* TRITON_RISCVSEMANTICS_H */ + diff --git a/src/libtriton/includes/triton/riscvSpecifications.hpp b/src/libtriton/includes/triton/riscvSpecifications.hpp new file mode 100644 index 000000000..4756eed37 --- /dev/null +++ b/src/libtriton/includes/triton/riscvSpecifications.hpp @@ -0,0 +1,365 @@ +// +//! \file +/* +** Copyright (C) - Triton +** +** This program is under the terms of the Apache License 2.0. +*/ + +#ifndef TRITON_RISCVSPECIFICATIONS_H +#define TRITON_RISCVSPECIFICATIONS_H + +#include +#include + +#include +#include +#include +#include + + + +//! The Triton namespace +namespace triton { +/*! + * \addtogroup triton + * @{ + */ + + //! The Architecture namespace + namespace arch { + /*! + * \ingroup triton + * \addtogroup arch + * @{ + */ + + //! The RISCV namespace + namespace riscv { + /*! + * \ingroup arch + * \addtogroup riscv + * @{ + */ + + //! \class riscvSpecifications + /*! \brief The riscvSpecifications class defines specifications about the RV32 and RV64 CPU */ + class riscvSpecifications { + protected: + //! List of registers specification available for this architecture. + std::unordered_map id2reg; + std::unordered_map name2id; + + public: + //! Constructor. + TRITON_EXPORT riscvSpecifications(triton::arch::architecture_e); + + //! Converts a capstone's register id to a triton's register id for RV64. + TRITON_EXPORT triton::arch::register_e capstoneRegisterToTritonRegister64(triton::uint32 id) const; + + //! Converts a capstone's register id to a triton's register id for RV32. + TRITON_EXPORT triton::arch::register_e capstoneRegisterToTritonRegister32(triton::uint32 id) const; + + //! Converts a capstone's instruction id to a triton's instruction id. + TRITON_EXPORT triton::uint32 capstoneInstructionToTritonInstruction(triton::uint32 id) const; + + //! Converts a capstone's group id to a triton's group id. + TRITON_EXPORT triton::arch::riscv::insn_group_e capstoneGroupToTritonGroup(triton::uint32 id) const; + + //! Returns memory access size if it is specified by instruction. + TRITON_EXPORT triton::uint32 getMemoryOperandSpecialSize(triton::uint32 id) const; + }; + + //! RISCV NOP instruction -- ADDI x0, x0, 0 + const triton::arch::Instruction nop = triton::arch::Instruction("\x13\x00\x00\x00", 4); + + //! The list of opcodes. + enum instruction_e { + ID_INS_INVALID = 0, + + ID_INS_ADD, + ID_INS_ADDI, + ID_INS_ADDIW, + ID_INS_ADDW, + ID_INS_AMOADD_D, + ID_INS_AMOADD_D_AQ, + ID_INS_AMOADD_D_AQ_RL, + ID_INS_AMOADD_D_RL, + ID_INS_AMOADD_W, + ID_INS_AMOADD_W_AQ, + ID_INS_AMOADD_W_AQ_RL, + ID_INS_AMOADD_W_RL, + ID_INS_AMOAND_D, + ID_INS_AMOAND_D_AQ, + ID_INS_AMOAND_D_AQ_RL, + ID_INS_AMOAND_D_RL, + ID_INS_AMOAND_W, + ID_INS_AMOAND_W_AQ, + ID_INS_AMOAND_W_AQ_RL, + ID_INS_AMOAND_W_RL, + ID_INS_AMOMAXU_D, + ID_INS_AMOMAXU_D_AQ, + ID_INS_AMOMAXU_D_AQ_RL, + ID_INS_AMOMAXU_D_RL, + ID_INS_AMOMAXU_W, + ID_INS_AMOMAXU_W_AQ, + ID_INS_AMOMAXU_W_AQ_RL, + ID_INS_AMOMAXU_W_RL, + ID_INS_AMOMAX_D, + ID_INS_AMOMAX_D_AQ, + ID_INS_AMOMAX_D_AQ_RL, + ID_INS_AMOMAX_D_RL, + ID_INS_AMOMAX_W, + ID_INS_AMOMAX_W_AQ, + ID_INS_AMOMAX_W_AQ_RL, + ID_INS_AMOMAX_W_RL, + ID_INS_AMOMINU_D, + ID_INS_AMOMINU_D_AQ, + ID_INS_AMOMINU_D_AQ_RL, + ID_INS_AMOMINU_D_RL, + ID_INS_AMOMINU_W, + ID_INS_AMOMINU_W_AQ, + ID_INS_AMOMINU_W_AQ_RL, + ID_INS_AMOMINU_W_RL, + ID_INS_AMOMIN_D, + ID_INS_AMOMIN_D_AQ, + ID_INS_AMOMIN_D_AQ_RL, + ID_INS_AMOMIN_D_RL, + ID_INS_AMOMIN_W, + ID_INS_AMOMIN_W_AQ, + ID_INS_AMOMIN_W_AQ_RL, + ID_INS_AMOMIN_W_RL, + ID_INS_AMOOR_D, + ID_INS_AMOOR_D_AQ, + ID_INS_AMOOR_D_AQ_RL, + ID_INS_AMOOR_D_RL, + ID_INS_AMOOR_W, + ID_INS_AMOOR_W_AQ, + ID_INS_AMOOR_W_AQ_RL, + ID_INS_AMOOR_W_RL, + ID_INS_AMOSWAP_D, + ID_INS_AMOSWAP_D_AQ, + ID_INS_AMOSWAP_D_AQ_RL, + ID_INS_AMOSWAP_D_RL, + ID_INS_AMOSWAP_W, + ID_INS_AMOSWAP_W_AQ, + ID_INS_AMOSWAP_W_AQ_RL, + ID_INS_AMOSWAP_W_RL, + ID_INS_AMOXOR_D, + ID_INS_AMOXOR_D_AQ, + ID_INS_AMOXOR_D_AQ_RL, + ID_INS_AMOXOR_D_RL, + ID_INS_AMOXOR_W, + ID_INS_AMOXOR_W_AQ, + ID_INS_AMOXOR_W_AQ_RL, + ID_INS_AMOXOR_W_RL, + ID_INS_AND, + ID_INS_ANDI, + ID_INS_AUIPC, + ID_INS_BEQ, + ID_INS_BGE, + ID_INS_BGEU, + ID_INS_BLT, + ID_INS_BLTU, + ID_INS_BNE, + ID_INS_CSRRC, + ID_INS_CSRRCI, + ID_INS_CSRRS, + ID_INS_CSRRSI, + ID_INS_CSRRW, + ID_INS_CSRRWI, + /* Compressed instructions */ + ID_INS_C_ADD, + ID_INS_C_ADDI, + ID_INS_C_ADDI16SP, + ID_INS_C_ADDI4SPN, + ID_INS_C_ADDIW, + ID_INS_C_ADDW, + ID_INS_C_AND, + ID_INS_C_ANDI, + ID_INS_C_BEQZ, + ID_INS_C_BNEZ, + ID_INS_C_EBREAK, + ID_INS_C_FLD, + ID_INS_C_FLDSP, + ID_INS_C_FLW, + ID_INS_C_FLWSP, + ID_INS_C_FSD, + ID_INS_C_FSDSP, + ID_INS_C_FSW, + ID_INS_C_FSWSP, + ID_INS_C_J, + ID_INS_C_JAL, + ID_INS_C_JALR, + ID_INS_C_JR, + ID_INS_C_LD, + ID_INS_C_LDSP, + ID_INS_C_LI, + ID_INS_C_LUI, + ID_INS_C_LW, + ID_INS_C_LWSP, + ID_INS_C_MV, + ID_INS_C_NOP, + ID_INS_C_OR, + ID_INS_C_SD, + ID_INS_C_SDSP, + ID_INS_C_SLLI, + ID_INS_C_SRAI, + ID_INS_C_SRLI, + ID_INS_C_SUB, + ID_INS_C_SUBW, + ID_INS_C_SW, + ID_INS_C_SWSP, + ID_INS_C_UNIMP, + ID_INS_C_XOR, + /* End of compressed instructions */ + ID_INS_DIV, + ID_INS_DIVU, + ID_INS_DIVUW, + ID_INS_DIVW, + ID_INS_EBREAK, + ID_INS_ECALL, + ID_INS_FADD_D, + ID_INS_FADD_S, + ID_INS_FCLASS_D, + ID_INS_FCLASS_S, + ID_INS_FCVT_D_L, + ID_INS_FCVT_D_LU, + ID_INS_FCVT_D_S, + ID_INS_FCVT_D_W, + ID_INS_FCVT_D_WU, + ID_INS_FCVT_LU_D, + ID_INS_FCVT_LU_S, + ID_INS_FCVT_L_D, + ID_INS_FCVT_L_S, + ID_INS_FCVT_S_D, + ID_INS_FCVT_S_L, + ID_INS_FCVT_S_LU, + ID_INS_FCVT_S_W, + ID_INS_FCVT_S_WU, + ID_INS_FCVT_WU_D, + ID_INS_FCVT_WU_S, + ID_INS_FCVT_W_D, + ID_INS_FCVT_W_S, + ID_INS_FDIV_D, + ID_INS_FDIV_S, + ID_INS_FENCE, + ID_INS_FENCE_I, + ID_INS_FENCE_TSO, + ID_INS_FEQ_D, + ID_INS_FEQ_S, + ID_INS_FLD, + ID_INS_FLE_D, + ID_INS_FLE_S, + ID_INS_FLT_D, + ID_INS_FLT_S, + ID_INS_FLW, + ID_INS_FMADD_D, + ID_INS_FMADD_S, + ID_INS_FMAX_D, + ID_INS_FMAX_S, + ID_INS_FMIN_D, + ID_INS_FMIN_S, + ID_INS_FMSUB_D, + ID_INS_FMSUB_S, + ID_INS_FMUL_D, + ID_INS_FMUL_S, + ID_INS_FMV_D_X, + ID_INS_FMV_W_X, + ID_INS_FMV_X_D, + ID_INS_FMV_X_W, + ID_INS_FNMADD_D, + ID_INS_FNMADD_S, + ID_INS_FNMSUB_D, + ID_INS_FNMSUB_S, + ID_INS_FSD, + ID_INS_FSGNJN_D, + ID_INS_FSGNJN_S, + ID_INS_FSGNJX_D, + ID_INS_FSGNJX_S, + ID_INS_FSGNJ_D, + ID_INS_FSGNJ_S, + ID_INS_FSQRT_D, + ID_INS_FSQRT_S, + ID_INS_FSUB_D, + ID_INS_FSUB_S, + ID_INS_FSW, + ID_INS_JAL, + ID_INS_JALR, + ID_INS_LB, + ID_INS_LBU, + ID_INS_LD, + ID_INS_LH, + ID_INS_LHU, + ID_INS_LR_D, + ID_INS_LR_D_AQ, + ID_INS_LR_D_AQ_RL, + ID_INS_LR_D_RL, + ID_INS_LR_W, + ID_INS_LR_W_AQ, + ID_INS_LR_W_AQ_RL, + ID_INS_LR_W_RL, + ID_INS_LUI, + ID_INS_LW, + ID_INS_LWU, + ID_INS_MRET, + ID_INS_MUL, + ID_INS_MULH, + ID_INS_MULHSU, + ID_INS_MULHU, + ID_INS_MULW, + ID_INS_OR, + ID_INS_ORI, + ID_INS_REM, + ID_INS_REMU, + ID_INS_REMUW, + ID_INS_REMW, + ID_INS_SB, + ID_INS_SC_D, + ID_INS_SC_D_AQ, + ID_INS_SC_D_AQ_RL, + ID_INS_SC_D_RL, + ID_INS_SC_W, + ID_INS_SC_W_AQ, + ID_INS_SC_W_AQ_RL, + ID_INS_SC_W_RL, + ID_INS_SD, + ID_INS_SFENCE_VMA, + ID_INS_SH, + ID_INS_SLL, + ID_INS_SLLI, + ID_INS_SLLIW, + ID_INS_SLLW, + ID_INS_SLT, + ID_INS_SLTI, + ID_INS_SLTIU, + ID_INS_SLTU, + ID_INS_SRA, + ID_INS_SRAI, + ID_INS_SRAIW, + ID_INS_SRAW, + ID_INS_SRET, + ID_INS_SRL, + ID_INS_SRLI, + ID_INS_SRLIW, + ID_INS_SRLW, + ID_INS_SUB, + ID_INS_SUBW, + ID_INS_SW, + ID_INS_UNIMP, + ID_INS_URET, + ID_INS_WFI, + ID_INS_XOR, + ID_INS_XORI, + + ID_INS_ENDING, //! + }; + + /*! @} End of RISCV namespace */ + }; + /*! @} End of arch namespace */ + }; +/*! @} End of triton namespace */ +}; + +#endif /* TRITON_RISCVSPECIFICATIONS_H */ diff --git a/src/libtriton/includes/triton/shortcutRegister.hpp b/src/libtriton/includes/triton/shortcutRegister.hpp index eb1e6fc7c..5dcbe9c54 100644 --- a/src/libtriton/includes/triton/shortcutRegister.hpp +++ b/src/libtriton/includes/triton/shortcutRegister.hpp @@ -49,6 +49,12 @@ namespace triton { #define REG_SPEC_NO_CAPSTONE REG_SPEC #include "triton/arm32.spec" + // ShortcutRegister set for RV32 is the same, + #define REG_SPEC(_0, _1, LOWER_NAME, _2, _3, _4, _5) \ + triton::arch::Register riscv_##LOWER_NAME; + #define REG_SPEC_NO_CAPSTONE REG_SPEC + #include "triton/riscv64.spec" + /*! Constructor */ ShortcutRegister() {}; @@ -69,6 +75,12 @@ namespace triton { this->arm32_##LOWER_NAME = triton::arch::Register(); #define REG_SPEC_NO_CAPSTONE REG_SPEC #include "triton/arm32.spec" + + // ShortcutRegister set for RV32 is the same, + #define REG_SPEC(_0, _1, LOWER_NAME, _2, _3, _4, _5) \ + this->riscv_##LOWER_NAME = triton::arch::Register(); + #define REG_SPEC_NO_CAPSTONE REG_SPEC + #include "triton/riscv64.spec" }; /*! Inits the shortcut */ @@ -130,6 +142,32 @@ namespace triton { } break; + case triton::arch::ARCH_RV64: { + #define REG_SPEC(CS_UPPER_NAME, UPPER_NAME, LOWER_NAME, ABI_NAME, RISCV_UPPER, RISCV_LOWER, MUTABLE) \ + this->riscv_##LOWER_NAME = triton::arch::Register(triton::arch::ID_REG_RV64_##UPPER_NAME, \ + #LOWER_NAME, \ + triton::arch::ID_REG_RV64_##UPPER_NAME, \ + RISCV_UPPER, \ + RISCV_LOWER, \ + true); + #define REG_SPEC_NO_CAPSTONE REG_SPEC + #include "triton/riscv64.spec" + } + break; + + case triton::arch::ARCH_RV32: { + #define REG_SPEC(CS_UPPER_NAME, UPPER_NAME, LOWER_NAME, ABI_NAME, RISCV_UPPER, RISCV_LOWER, MUTABLE) \ + this->riscv_##LOWER_NAME = triton::arch::Register(triton::arch::ID_REG_RV32_##UPPER_NAME, \ + #LOWER_NAME, \ + triton::arch::ID_REG_RV32_##UPPER_NAME, \ + RISCV_UPPER, \ + RISCV_LOWER, \ + true); + #define REG_SPEC_NO_CAPSTONE REG_SPEC + #include "triton/riscv32.spec" + } + break; + default: throw triton::exceptions::Architecture("ShortcutRegister::init(): Invalid architecture."); } diff --git a/src/scripts/docker/Dockerfile b/src/scripts/docker/Dockerfile index 6e027846f..cf08bac3b 100644 --- a/src/scripts/docker/Dockerfile +++ b/src/scripts/docker/Dockerfile @@ -58,5 +58,5 @@ RUN echo "[+] Download, build and install Capstone" && \ wget -q https://github.com/capstone-engine/capstone/archive/refs/tags/5.0.1.tar.gz -O capstone-5.0.1.tar.gz && \ tar xf capstone-5.0.1.tar.gz && \ cd ./capstone-5.0.1 && \ - ./make.sh && \ + CAPSTONE_ARCHS="arm aarch64 riscv x86" ./make.sh && \ sudo make install diff --git a/src/testers/CMakeLists.txt b/src/testers/CMakeLists.txt index 745a809eb..614f19a5b 100644 --- a/src/testers/CMakeLists.txt +++ b/src/testers/CMakeLists.txt @@ -5,6 +5,8 @@ if((${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR ${CMAKE_SYSTEM_NAME} MATCHES "Darwin add_test(NAME UnicornAArch64Semantics COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/aarch64/unicorn_test_aarch64.py) add_test(NAME UnicornX86Semantics COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/x86/unicorn_test_x86.py) + add_test(NAME UnicornRiscv64Semantics COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/riscv/unicorn_test_riscv64.py) + add_test(NAME UnicornRiscv32Semantics COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/riscv/unicorn_test_riscv32.py) add_test(NAME UnicornARM32Semantics1 COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/arm32/unicorn_test_arm32_branch_arm_1.py) add_test(NAME UnicornARM32Semantics2 COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/arm32/unicorn_test_arm32_branch_arm_2.py) add_test(NAME UnicornARM32Semantics3 COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/arm32/unicorn_test_arm32_branch_pc_arm_1.py) @@ -44,6 +46,8 @@ if((${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR ${CMAKE_SYSTEM_NAME} MATCHES "Darwin set_property(TEST UnicornAArch64Semantics UnicornX86Semantics + UnicornRiscv64Semantics + UnicornRiscv32Semantics UnicornARM32Semantics1 UnicornARM32Semantics2 UnicornARM32Semantics3 diff --git a/src/testers/riscv/unicorn_test_riscv32.py b/src/testers/riscv/unicorn_test_riscv32.py new file mode 100644 index 000000000..2682a6467 --- /dev/null +++ b/src/testers/riscv/unicorn_test_riscv32.py @@ -0,0 +1,614 @@ +#!/usr/bin/env python3 +## -*- coding: utf-8 -*- + +from __future__ import print_function + +from triton import * +from unicorn import * +from unicorn.riscv_const import * +from struct import pack + +import sys +import pprint + +ADDR = 0x100000 +STACK = 0x200000 +HEAP = 0x300000 +SIZE = 5 * 1024 * 1024 + +CODE = [ + # ADDI + (b"\x93\x05\x16\x00", "addi x11, x12, #1"), + (b"\x13\x00\xe0\x00", "addi x0, x0, #0xe"), + (b"\x13\x05\x00\x00", "addi x10, x0, #0"), + (b"\x13\x00\x00\x00", "addi x0, x0, #0"), # nop + (b"\x13\x00\x00\x00", "addi x0, x0, #0"), # nop + (b"\x13\x00\x00\x00", "addi x0, x0, #0"), # nop + (b"\x93\x05\x16\x00", "addi x11, x12, #1"), + (b"\x93\x05\x06\x00", "addi x11, x12, #0"), + (b"\x13\x05\xe0\x00", "addi x10, x0, #0xe"), + (b"\x13\x03\x43\x00", "addi x6, x6, #4"), + (b"\x49\x13", "c.addi x1, x1, #1"), + (b"\x49\x13", "c.addi x6, x6, #-0xe"), + (b"\x09\x16", "c.addi x12, x12, #-30"), + (b"\x11\x01", "c.addi x2, x2, #4"), + (b"\x75\x61", "c.addi16sp x2, x2, #368"), + (b"\x40\x00", "c.addi4spn x8, x2, #4"), + (b"\x8c\x02", "c.addi4spn x10, x2, #320"), + (b"\x85\x47", "c.li x15, #1"), + (b"\x49\x4c", "c.li x24, #18"), + (b"\x09\x54", "c.li x8, #-30"), + (b"\x01\x00", "c.nop"), + (b"\x5d\x00", "c.nop 23"), + (b"\x65\x00", "c.nop 25"), + + # ADD + (b"\x33\x05\x00\x00", "add x10, x0, x0"), + (b"\x33\x86\xb0\x00", "add x12, x1, x11"), + (b"\xb3\x05\x06\x00", "add x11, x12, x0"), + (b"\xb3\x05\xc0\x00", "add x11, x0, x12"), + (b"\xbe\x95", "c.add x11, x11, x15"), + (b"\x0a\x9a", "c.add x20, x20, x2"), + (b"\x0a\x88", "c.mv x16, x2"), + (b"\xb2\x8a", "c.mv x21, x12"), + + # AND(I) + (b"\x13\xf0\xf0\x0f", "andi x0, x1, #0xff"), + (b"\x13\x75\xf0\x0f", "andi x10, x0, #0xff"), + (b"\x93\x76\x17\x00", "andi x13, x14, #0x01"), + (b"\x93\x76\x07\x01", "andi x13, x14, #0x10"), + (b"\x49\x13", "c.andi x14, x14, #2"), + (b"\x19\x98", "c.andi x8, x8, #-26"), + (b"\xb3\x71\x52\x00", "and x3, x4, x5"), + (b"\xb3\x75\xc5\x00", "and x11, x10, x12"), + (b"\x71\x8f", "c.and x14, x14, x12"), + + # AUIPC + (b"\x17\xe5\xcd\xab", "auipc x10, #0xabcde"), + (b"\x17\x15\x00\x00", "auipc x10, #0x1"), + (b"\x17\xd9\xf1\xe2", "auipc x18, #0xf1e2d"), + (b"\x17\x10\x00\x00", "auipc x0, #0x1"), + + # SB / SH / SW + (b"\x23\x0c\xa1\x00", "sb x10, 0x18(sp)"), + (b"\xa3\x0c\xa1\x00", "sb x10, 0x19(sp)"), + (b"\x23\x00\xc1\x02", "sb x12, 0x20(sp)"), + (b"\x23\x2a\xe1\x00", "sw x14, 0x14(sp)"), + (b"\x23\x20\xa1\x02", "sw x10, 0x20(sp)"), + (b"\x23\x11\xe1\x02", "sh x14, 0x22(sp)"), + (b"\x23\x10\x01\x00", "sh x0, 0(sp)"), + (b"\x23\x12\xa1\x02", "sh x10, 0x24(sp)"), + (b"\x23\x20\xe1\x00", "sw x14, 0(sp)"), + + # LB / LH / LW + (b"\x03\x25\x01\x00", "lw x10, 0(sp)"), + (b"\x03\x07\x01\x00", "lb x14, 0(sp)"), + (b"\x03\x07\x01\x02", "lb x14, 0x20(sp)"), + (b"\x83\x15\x81\x01", "lh x11, 0x18(sp)"), + # LBU / LHU + (b"\x03\x4a\x91\x01", "lbu x20, 0x19(sp)"), + (b"\x83\x55\x41\x02", "lhu x11, 0x24(sp)"), + + # Compressed load/store + (b"\x0a\x85", "c.mv x10, x2"), + (b"\x4c\x49", "c.lw x11, 0x14(x10)"), + (b"\x42\x43", "c.lwsp x6, 0x10(sp)"), + (b"\x10\xcd", "c.sw x12, 0x18(x10)"), + (b"\x42\xc8", "c.swsp x16, 0x10(sp)"), + + #(b"\x01\x25", "c.jal 0x600"), # 32-bit only + + # LUI + (b"\x37\xfa\xff\xff", "lui x20, #0xfffff"), + (b"\xb7\x0a\x01\x01", "lui x21, #0x1010"), + (b"\x37\x5b\x34\x12", "lui x22, #0x12345"), + (b"\x37\x00\x00\x00", "lui x0, #0"), + (b"\x65\x67", "c.lui x14, #0x19"), + (b"\x75\x74", "c.lui x8, #0xffffd"), + + # OR(I) + (b"\x93\x65\x05\x0f", "ori x11, x10, #0xf0"), + (b"\x93\x65\x76\x00", "ori x11, x12, #0x7"), + (b"\x33\x66\xb5\x00", "or x12, x10, x11"), + (b"\x51\x8f", "c.or x14, x14, x12"), + + # MUL + (b"\x33\x85\xb5\x02", "mul x10, x11, x11"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x07\xa0\x02", "mul x14, x0, x10"), + (b"\x33\x17\xc6\x02", "mulh x14, x12, x12"), + (b"\x33\x27\xc6\x02", "mulhsu x14, x12, x12"), + (b"\x33\x27\xe6\x02", "mulhsu x14, x12, x14"), + (b"\x33\x27\xe6\x02", "mulhsu x14, x12, x14"), + (b"\x33\x27\xe6\x02", "mulhsu x14, x12, x14"), + (b"\xb3\x26\xb5\x02", "mulhsu x13, x10, x11"), + (b"\x33\x37\xe6\x02", "mulhu x14, x12, x14"), + (b"\xb3\x36\xe5\x02", "mulhu x13, x10, x14"), + + # DIV/U + (b"\x33\x46\xa6\x02", "div x12, x12, x10"), + (b"\x33\x56\xa6\x02", "divu x12, x12, x10"), + + # REM/U + (b"\xb3\x65\xa6\x02", "rem x11, x12, x10"), + (b"\xb3\x75\xa6\x02", "remu x11, x12, x10"), + + # SUB/W + (b"\xb3\x05\xa0\x40", "sub x11, x0, x10"), + (b"\xb3\x05\xb0\x40", "sub x11, x0, x11"), # neg + (b"\xb3\x05\xa7\x40", "sub x11, x14, x10"), + (b"\x33\x00\xe7\x40", "sub x0, x14, x14"), + (b"\x89\x8d", "c.sub x11, x11, x10"), + + # XOR(I) + (b"\xb3\x45\xb5\x00", "xor x11, x10, x11"), + (b"\x33\x45\xa5\x00", "xor x10, x10, x10"), + (b"\x33\x45\x00\x00", "xor x10, x0, x0"), + (b"\xb9\x8f", "c.xor x15, x15, x14"), + (b"\x93\x47\x36\x0f", "xori x15, x12, #0xf3"), + (b"\x93\x47\xe6\xff", "xori x15, x12, #-2"), + (b"\x93\x47\xf6\xff", "xori x15, x12, #-1"), # not + + # SLT + (b"\x33\x28\xb5\x00", "slt x16, x10, x11"), + (b"\x33\x28\x84\x00", "slt x16, x8, x8"), + (b"\xb3\xa0\x05\x00", "slt x1, x11, x0"), # sltz + (b"\xb3\x20\xb0\x00", "slt x1, x0, x11"), # sgtz + (b"\xb3\x20\x00\x00", "slt x1, x0, x0"), # sltz + (b"\xb3\xa0\xa0\x00", "slt x1, x1, x10"), + # SLTI + (b"\x13\xa8\x15\x00", "slti x16, x11, #1"), + (b"\x13\x28\x87\xff", "slti x16, x14, #-8"), + (b"\x13\x28\xd7\x01", "slti x16, x14, #29"), + # SLT(I)U + (b"\x93\x30\x15\x00", "sltiu x1, x10, #1"), # seqz + (b"\x13\xb8\x05\x01", "sltiu x16, x11, #0x10"), + (b"\x13\xb8\xb5\xff", "sltiu x16, x11, #-5"), + (b"\x33\xb8\xb5\x00", "sltu x16, x11, x11"), + (b"\x33\x38\xb5\x00", "sltu x16, x10, x11"), + (b"\xb3\x30\xa0\x00", "sltu x1, x0, x10"), # snez + (b"\xb3\x30\xb0\x00", "sltu x1, x0, x11"), # snez + + # SLL + (b"\xb3\x15\xb5\x00", "sll x11, x10, x11"), + (b"\x93\x10\x85\x00", "slli x1, x10, #8"), + (b"\x93\x15\xf5\x00", "slli x11, x10, #0xf"), + (b"\x12\x06", "c.slli x12, x12, #0x4"), + # SRA + (b"\xb3\x55\xb5\x40", "sra x11, x10, x11"), + (b"\x93\x55\x85\x40", "srai x11, x10, #8"), + (b"\x93\x55\xf5\x40", "srai x11, x10, #0xf"), + (b"\x85\x85", "c.srai x11, x11, #0x1"), + # SRL + (b"\xb3\x55\xb5\x00", "srl x11, x10, x11"), + (b"\x93\x55\x85\x00", "srli x11, x10, #8"), + (b"\x93\x55\xf5\x00", "srli x11, x10, #0xf"), + (b"\x85\x81", "c.srli x11, x11, #0x1"), + +] + +def emu_with_unicorn(opcode, istate): + # Initialize emulator in RV32 mode + mu = Uc(UC_ARCH_RISCV, UC_MODE_RISCV32) + + # map memory for this emulation + mu.mem_map(ADDR, SIZE) + + # write machine code to be emulated to memory + index = 0 + for op, _ in CODE: + mu.mem_write(ADDR+index, op) + index += len(op) + + mu.mem_write(STACK, bytes(istate['stack'])) + mu.mem_write(HEAP, bytes(istate['heap'])) + mu.reg_write(UC_RISCV_REG_X0, istate['x0']) + mu.reg_write(UC_RISCV_REG_X1, istate['x1']) + mu.reg_write(UC_RISCV_REG_X2, istate['x2']) + mu.reg_write(UC_RISCV_REG_X3, istate['x3']) + mu.reg_write(UC_RISCV_REG_X4, istate['x4']) + mu.reg_write(UC_RISCV_REG_X5, istate['x5']) + mu.reg_write(UC_RISCV_REG_X6, istate['x6']) + mu.reg_write(UC_RISCV_REG_X7, istate['x7']) + mu.reg_write(UC_RISCV_REG_X8, istate['x8']) + mu.reg_write(UC_RISCV_REG_X9, istate['x9']) + mu.reg_write(UC_RISCV_REG_X10, istate['x10']) + mu.reg_write(UC_RISCV_REG_X11, istate['x11']) + mu.reg_write(UC_RISCV_REG_X12, istate['x12']) + mu.reg_write(UC_RISCV_REG_X13, istate['x13']) + mu.reg_write(UC_RISCV_REG_X14, istate['x14']) + mu.reg_write(UC_RISCV_REG_X15, istate['x15']) + mu.reg_write(UC_RISCV_REG_X16, istate['x16']) + mu.reg_write(UC_RISCV_REG_X17, istate['x17']) + mu.reg_write(UC_RISCV_REG_X18, istate['x18']) + mu.reg_write(UC_RISCV_REG_X19, istate['x19']) + mu.reg_write(UC_RISCV_REG_X20, istate['x20']) + mu.reg_write(UC_RISCV_REG_X21, istate['x21']) + mu.reg_write(UC_RISCV_REG_X22, istate['x22']) + mu.reg_write(UC_RISCV_REG_X23, istate['x23']) + mu.reg_write(UC_RISCV_REG_X24, istate['x24']) + mu.reg_write(UC_RISCV_REG_X25, istate['x25']) + mu.reg_write(UC_RISCV_REG_X26, istate['x26']) + mu.reg_write(UC_RISCV_REG_X27, istate['x27']) + mu.reg_write(UC_RISCV_REG_X28, istate['x28']) + mu.reg_write(UC_RISCV_REG_X29, istate['x29']) + mu.reg_write(UC_RISCV_REG_X30, istate['x30']) + mu.reg_write(UC_RISCV_REG_X31, istate['x31']) + mu.reg_write(UC_RISCV_REG_F0, istate['f0']) + mu.reg_write(UC_RISCV_REG_F1, istate['f1']) + mu.reg_write(UC_RISCV_REG_F2, istate['f2']) + mu.reg_write(UC_RISCV_REG_F3, istate['f3']) + mu.reg_write(UC_RISCV_REG_F4, istate['f4']) + mu.reg_write(UC_RISCV_REG_F5, istate['f5']) + mu.reg_write(UC_RISCV_REG_F6, istate['f6']) + mu.reg_write(UC_RISCV_REG_F7, istate['f7']) + mu.reg_write(UC_RISCV_REG_F8, istate['f8']) + mu.reg_write(UC_RISCV_REG_F9, istate['f9']) + mu.reg_write(UC_RISCV_REG_F10, istate['f10']) + mu.reg_write(UC_RISCV_REG_F11, istate['f11']) + mu.reg_write(UC_RISCV_REG_F12, istate['f12']) + mu.reg_write(UC_RISCV_REG_F13, istate['f13']) + mu.reg_write(UC_RISCV_REG_F14, istate['f14']) + mu.reg_write(UC_RISCV_REG_F15, istate['f15']) + mu.reg_write(UC_RISCV_REG_F16, istate['f16']) + mu.reg_write(UC_RISCV_REG_F17, istate['f17']) + mu.reg_write(UC_RISCV_REG_F18, istate['f18']) + mu.reg_write(UC_RISCV_REG_F19, istate['f19']) + mu.reg_write(UC_RISCV_REG_F20, istate['f20']) + mu.reg_write(UC_RISCV_REG_F21, istate['f21']) + mu.reg_write(UC_RISCV_REG_F22, istate['f22']) + mu.reg_write(UC_RISCV_REG_F23, istate['f23']) + mu.reg_write(UC_RISCV_REG_F24, istate['f24']) + mu.reg_write(UC_RISCV_REG_F25, istate['f25']) + mu.reg_write(UC_RISCV_REG_F26, istate['f26']) + mu.reg_write(UC_RISCV_REG_F27, istate['f27']) + mu.reg_write(UC_RISCV_REG_F28, istate['f28']) + mu.reg_write(UC_RISCV_REG_F29, istate['f29']) + mu.reg_write(UC_RISCV_REG_F30, istate['f30']) + mu.reg_write(UC_RISCV_REG_F31, istate['f31']) + mu.reg_write(UC_RISCV_REG_PC, istate['pc']) + + # emulate code in infinite time & unlimited instructions + mu.emu_start(istate['pc'], istate['pc'] + len(opcode), 0, 1) + + ostate = { + "stack": mu.mem_read(STACK, 0x100), + "heap": mu.mem_read(HEAP, 0x100), + "x0": mu.reg_read(UC_RISCV_REG_X0), + "x1": mu.reg_read(UC_RISCV_REG_X1), + "x2": mu.reg_read(UC_RISCV_REG_X2), + "x3": mu.reg_read(UC_RISCV_REG_X3), + "x4": mu.reg_read(UC_RISCV_REG_X4), + "x5": mu.reg_read(UC_RISCV_REG_X5), + "x6": mu.reg_read(UC_RISCV_REG_X6), + "x7": mu.reg_read(UC_RISCV_REG_X7), + "x8": mu.reg_read(UC_RISCV_REG_X8), + "x9": mu.reg_read(UC_RISCV_REG_X9), + "x10": mu.reg_read(UC_RISCV_REG_X10), + "x11": mu.reg_read(UC_RISCV_REG_X11), + "x12": mu.reg_read(UC_RISCV_REG_X12), + "x13": mu.reg_read(UC_RISCV_REG_X13), + "x14": mu.reg_read(UC_RISCV_REG_X14), + "x15": mu.reg_read(UC_RISCV_REG_X15), + "x16": mu.reg_read(UC_RISCV_REG_X16), + "x17": mu.reg_read(UC_RISCV_REG_X17), + "x18": mu.reg_read(UC_RISCV_REG_X18), + "x19": mu.reg_read(UC_RISCV_REG_X19), + "x20": mu.reg_read(UC_RISCV_REG_X20), + "x21": mu.reg_read(UC_RISCV_REG_X21), + "x22": mu.reg_read(UC_RISCV_REG_X22), + "x23": mu.reg_read(UC_RISCV_REG_X23), + "x24": mu.reg_read(UC_RISCV_REG_X24), + "x25": mu.reg_read(UC_RISCV_REG_X25), + "x26": mu.reg_read(UC_RISCV_REG_X26), + "x27": mu.reg_read(UC_RISCV_REG_X27), + "x28": mu.reg_read(UC_RISCV_REG_X28), + "x29": mu.reg_read(UC_RISCV_REG_X29), + "x30": mu.reg_read(UC_RISCV_REG_X30), + "x31": mu.reg_read(UC_RISCV_REG_X31), + "f0": mu.reg_read(UC_RISCV_REG_F0), + "f1": mu.reg_read(UC_RISCV_REG_F1), + "f2": mu.reg_read(UC_RISCV_REG_F2), + "f3": mu.reg_read(UC_RISCV_REG_F3), + "f4": mu.reg_read(UC_RISCV_REG_F4), + "f5": mu.reg_read(UC_RISCV_REG_F5), + "f6": mu.reg_read(UC_RISCV_REG_F6), + "f7": mu.reg_read(UC_RISCV_REG_F7), + "f8": mu.reg_read(UC_RISCV_REG_F8), + "f9": mu.reg_read(UC_RISCV_REG_F9), + "f10": mu.reg_read(UC_RISCV_REG_F10), + "f11": mu.reg_read(UC_RISCV_REG_F11), + "f12": mu.reg_read(UC_RISCV_REG_F12), + "f13": mu.reg_read(UC_RISCV_REG_F13), + "f14": mu.reg_read(UC_RISCV_REG_F14), + "f15": mu.reg_read(UC_RISCV_REG_F15), + "f16": mu.reg_read(UC_RISCV_REG_F16), + "f17": mu.reg_read(UC_RISCV_REG_F17), + "f18": mu.reg_read(UC_RISCV_REG_F18), + "f19": mu.reg_read(UC_RISCV_REG_F19), + "f20": mu.reg_read(UC_RISCV_REG_F20), + "f21": mu.reg_read(UC_RISCV_REG_F21), + "f22": mu.reg_read(UC_RISCV_REG_F22), + "f23": mu.reg_read(UC_RISCV_REG_F23), + "f24": mu.reg_read(UC_RISCV_REG_F24), + "f25": mu.reg_read(UC_RISCV_REG_F25), + "f26": mu.reg_read(UC_RISCV_REG_F26), + "f27": mu.reg_read(UC_RISCV_REG_F27), + "f28": mu.reg_read(UC_RISCV_REG_F28), + "f29": mu.reg_read(UC_RISCV_REG_F29), + "f30": mu.reg_read(UC_RISCV_REG_F30), + "f31": mu.reg_read(UC_RISCV_REG_F31), + "pc": mu.reg_read(UC_RISCV_REG_PC), + } + return ostate + + +def emu_with_triton(opcode, istate): + ctx = TritonContext() + ctx.setArchitecture(ARCH.RV32) + + inst = Instruction(opcode) + inst.setAddress(istate['pc']) + + ctx.setConcreteMemoryAreaValue(STACK, bytes(istate['stack'])) + ctx.setConcreteMemoryAreaValue(HEAP, bytes(istate['heap'])) + ctx.setConcreteRegisterValue(ctx.registers.x0, 0) + ctx.setConcreteRegisterValue(ctx.registers.x1, istate['x1']) + ctx.setConcreteRegisterValue(ctx.registers.x2, istate['x2']) + ctx.setConcreteRegisterValue(ctx.registers.x3, istate['x3']) + ctx.setConcreteRegisterValue(ctx.registers.x4, istate['x4']) + ctx.setConcreteRegisterValue(ctx.registers.x5, istate['x5']) + ctx.setConcreteRegisterValue(ctx.registers.x6, istate['x6']) + ctx.setConcreteRegisterValue(ctx.registers.x7, istate['x7']) + ctx.setConcreteRegisterValue(ctx.registers.x8, istate['x8']) + ctx.setConcreteRegisterValue(ctx.registers.x9, istate['x9']) + ctx.setConcreteRegisterValue(ctx.registers.x10, istate['x10']) + ctx.setConcreteRegisterValue(ctx.registers.x11, istate['x11']) + ctx.setConcreteRegisterValue(ctx.registers.x12, istate['x12']) + ctx.setConcreteRegisterValue(ctx.registers.x13, istate['x13']) + ctx.setConcreteRegisterValue(ctx.registers.x14, istate['x14']) + ctx.setConcreteRegisterValue(ctx.registers.x15, istate['x15']) + ctx.setConcreteRegisterValue(ctx.registers.x16, istate['x16']) + ctx.setConcreteRegisterValue(ctx.registers.x17, istate['x17']) + ctx.setConcreteRegisterValue(ctx.registers.x18, istate['x18']) + ctx.setConcreteRegisterValue(ctx.registers.x19, istate['x19']) + ctx.setConcreteRegisterValue(ctx.registers.x20, istate['x20']) + ctx.setConcreteRegisterValue(ctx.registers.x21, istate['x21']) + ctx.setConcreteRegisterValue(ctx.registers.x22, istate['x22']) + ctx.setConcreteRegisterValue(ctx.registers.x23, istate['x23']) + ctx.setConcreteRegisterValue(ctx.registers.x24, istate['x24']) + ctx.setConcreteRegisterValue(ctx.registers.x25, istate['x25']) + ctx.setConcreteRegisterValue(ctx.registers.x26, istate['x26']) + ctx.setConcreteRegisterValue(ctx.registers.x27, istate['x27']) + ctx.setConcreteRegisterValue(ctx.registers.x28, istate['x28']) + ctx.setConcreteRegisterValue(ctx.registers.x29, istate['x29']) + ctx.setConcreteRegisterValue(ctx.registers.x30, istate['x30']) + ctx.setConcreteRegisterValue(ctx.registers.x31, istate['x31']) + ctx.setConcreteRegisterValue(ctx.registers.f0, istate['f0']) + ctx.setConcreteRegisterValue(ctx.registers.f1, istate['f1']) + ctx.setConcreteRegisterValue(ctx.registers.f2, istate['f2']) + ctx.setConcreteRegisterValue(ctx.registers.f3, istate['f3']) + ctx.setConcreteRegisterValue(ctx.registers.f4, istate['f4']) + ctx.setConcreteRegisterValue(ctx.registers.f5, istate['f5']) + ctx.setConcreteRegisterValue(ctx.registers.f6, istate['f6']) + ctx.setConcreteRegisterValue(ctx.registers.f7, istate['f7']) + ctx.setConcreteRegisterValue(ctx.registers.f8, istate['f8']) + ctx.setConcreteRegisterValue(ctx.registers.f9, istate['f9']) + ctx.setConcreteRegisterValue(ctx.registers.f10, istate['f10']) + ctx.setConcreteRegisterValue(ctx.registers.f11, istate['f11']) + ctx.setConcreteRegisterValue(ctx.registers.f12, istate['f12']) + ctx.setConcreteRegisterValue(ctx.registers.f13, istate['f13']) + ctx.setConcreteRegisterValue(ctx.registers.f14, istate['f14']) + ctx.setConcreteRegisterValue(ctx.registers.f15, istate['f15']) + ctx.setConcreteRegisterValue(ctx.registers.f16, istate['f16']) + ctx.setConcreteRegisterValue(ctx.registers.f17, istate['f17']) + ctx.setConcreteRegisterValue(ctx.registers.f18, istate['f18']) + ctx.setConcreteRegisterValue(ctx.registers.f19, istate['f19']) + ctx.setConcreteRegisterValue(ctx.registers.f20, istate['f20']) + ctx.setConcreteRegisterValue(ctx.registers.f21, istate['f21']) + ctx.setConcreteRegisterValue(ctx.registers.f22, istate['f22']) + ctx.setConcreteRegisterValue(ctx.registers.f23, istate['f23']) + ctx.setConcreteRegisterValue(ctx.registers.f24, istate['f24']) + ctx.setConcreteRegisterValue(ctx.registers.f25, istate['f25']) + ctx.setConcreteRegisterValue(ctx.registers.f26, istate['f26']) + ctx.setConcreteRegisterValue(ctx.registers.f27, istate['f27']) + ctx.setConcreteRegisterValue(ctx.registers.f28, istate['f28']) + ctx.setConcreteRegisterValue(ctx.registers.f29, istate['f29']) + ctx.setConcreteRegisterValue(ctx.registers.f30, istate['f30']) + ctx.setConcreteRegisterValue(ctx.registers.f31, istate['f31']) + ctx.setConcreteRegisterValue(ctx.registers.pc, istate['pc']) + + ctx.processing(inst) + + #print + #print(inst) + #for x in inst.getSymbolicExpressions(): + # print(x) + #print + + ostate = { + "stack": ctx.getConcreteMemoryAreaValue(STACK, 0x100), + "heap": ctx.getConcreteMemoryAreaValue(HEAP, 0x100), + + "x0": 0, + "x1": ctx.getSymbolicRegisterValue(ctx.registers.x1), + "x2": ctx.getSymbolicRegisterValue(ctx.registers.x2), + "x3": ctx.getSymbolicRegisterValue(ctx.registers.x3), + "x4": ctx.getSymbolicRegisterValue(ctx.registers.x4), + "x5": ctx.getSymbolicRegisterValue(ctx.registers.x5), + "x6": ctx.getSymbolicRegisterValue(ctx.registers.x6), + "x7": ctx.getSymbolicRegisterValue(ctx.registers.x7), + "x8": ctx.getSymbolicRegisterValue(ctx.registers.x8), + "x9": ctx.getSymbolicRegisterValue(ctx.registers.x9), + "x10": ctx.getSymbolicRegisterValue(ctx.registers.x10), + "x11": ctx.getSymbolicRegisterValue(ctx.registers.x11), + "x12": ctx.getSymbolicRegisterValue(ctx.registers.x12), + "x13": ctx.getSymbolicRegisterValue(ctx.registers.x13), + "x14": ctx.getSymbolicRegisterValue(ctx.registers.x14), + "x15": ctx.getSymbolicRegisterValue(ctx.registers.x15), + "x16": ctx.getSymbolicRegisterValue(ctx.registers.x16), + "x17": ctx.getSymbolicRegisterValue(ctx.registers.x17), + "x18": ctx.getSymbolicRegisterValue(ctx.registers.x18), + "x19": ctx.getSymbolicRegisterValue(ctx.registers.x19), + "x20": ctx.getSymbolicRegisterValue(ctx.registers.x20), + "x21": ctx.getSymbolicRegisterValue(ctx.registers.x21), + "x22": ctx.getSymbolicRegisterValue(ctx.registers.x22), + "x23": ctx.getSymbolicRegisterValue(ctx.registers.x23), + "x24": ctx.getSymbolicRegisterValue(ctx.registers.x24), + "x25": ctx.getSymbolicRegisterValue(ctx.registers.x25), + "x26": ctx.getSymbolicRegisterValue(ctx.registers.x26), + "x27": ctx.getSymbolicRegisterValue(ctx.registers.x27), + "x28": ctx.getSymbolicRegisterValue(ctx.registers.x28), + "x29": ctx.getSymbolicRegisterValue(ctx.registers.x29), + "x30": ctx.getSymbolicRegisterValue(ctx.registers.x30), + "x31": ctx.getSymbolicRegisterValue(ctx.registers.x31), + "f0": ctx.getSymbolicRegisterValue(ctx.registers.f0), + "f1": ctx.getSymbolicRegisterValue(ctx.registers.f1), + "f2": ctx.getSymbolicRegisterValue(ctx.registers.f2), + "f3": ctx.getSymbolicRegisterValue(ctx.registers.f3), + "f4": ctx.getSymbolicRegisterValue(ctx.registers.f4), + "f5": ctx.getSymbolicRegisterValue(ctx.registers.f5), + "f6": ctx.getSymbolicRegisterValue(ctx.registers.f6), + "f7": ctx.getSymbolicRegisterValue(ctx.registers.f7), + "f8": ctx.getSymbolicRegisterValue(ctx.registers.f8), + "f9": ctx.getSymbolicRegisterValue(ctx.registers.f9), + "f10": ctx.getSymbolicRegisterValue(ctx.registers.f10), + "f11": ctx.getSymbolicRegisterValue(ctx.registers.f11), + "f12": ctx.getSymbolicRegisterValue(ctx.registers.f12), + "f13": ctx.getSymbolicRegisterValue(ctx.registers.f13), + "f14": ctx.getSymbolicRegisterValue(ctx.registers.f14), + "f15": ctx.getSymbolicRegisterValue(ctx.registers.f15), + "f16": ctx.getSymbolicRegisterValue(ctx.registers.f16), + "f17": ctx.getSymbolicRegisterValue(ctx.registers.f17), + "f18": ctx.getSymbolicRegisterValue(ctx.registers.f18), + "f19": ctx.getSymbolicRegisterValue(ctx.registers.f19), + "f20": ctx.getSymbolicRegisterValue(ctx.registers.f20), + "f21": ctx.getSymbolicRegisterValue(ctx.registers.f21), + "f22": ctx.getSymbolicRegisterValue(ctx.registers.f22), + "f23": ctx.getSymbolicRegisterValue(ctx.registers.f23), + "f24": ctx.getSymbolicRegisterValue(ctx.registers.f24), + "f25": ctx.getSymbolicRegisterValue(ctx.registers.f25), + "f26": ctx.getSymbolicRegisterValue(ctx.registers.f26), + "f27": ctx.getSymbolicRegisterValue(ctx.registers.f27), + "f28": ctx.getSymbolicRegisterValue(ctx.registers.f28), + "f29": ctx.getSymbolicRegisterValue(ctx.registers.f29), + "f30": ctx.getSymbolicRegisterValue(ctx.registers.f30), + "f31": ctx.getSymbolicRegisterValue(ctx.registers.f31), + "pc": ctx.getSymbolicRegisterValue(ctx.registers.pc), + } + return ostate + + +def diff_state(state1, state2): + for k, v in list(state1.items()): + if (k == 'heap' or k == 'stack') and v != state2[k]: + print('\t%s: (UC) != (TT)' %(k)) + elif not (k == 'heap' or k == 'stack') and v != state2[k]: + print('\t%s: %#x (UC) != %#x (TT)' %(k, v, state2[k])) + return + + +if __name__ == '__main__': + # initial state + state = { + "stack": bytearray(b"".join([pack('B', 255 - i) for i in range(256)])), + "heap": bytearray(b"".join([pack('B', i) for i in range(256)])), + "x0": 0x0, + "x1": 0x0, + "x2": STACK, + "x3": 0x0, + "x4": 0x0, + "x5": 0x0, + "x6": 0x0, + "x7": 0x0, + "x8": 0x0, + "x9": 0x0, + "x10": 0x0, + "x11": 0x0, + "x12": 0x0, + "x13": 0x0, + "x14": 0x0, + "x15": 0x0, + "x16": 0x0, + "x17": 0x0, + "x18": 0x0, + "x19": 0x0, + "x20": 0x0, + "x21": 0x0, + "x22": 0x0, + "x23": 0x0, + "x24": 0x0, + "x25": 0x0, + "x26": 0x0, + "x27": 0x0, + "x28": 0x0, + "x29": 0x0, + "x30": 0x0, + "x31": 0x0, + "f0": 0x0123456789abcdef, + "f1": 0xfedcba9876543210, + "f2": 0xfefedcdc56567878, + "f3": 0x123456789098cd01, + "f4": 0x0, + "f5": 0x0, + "f6": 0x0, + "f7": 0x0, + "f8": 0x0, + "f9": 0x0, + "f10": 0x0, + "f11": 0x0, + "f12": 0x0, + "f13": 0x0, + "f14": 0x0, + "f15": 0x0, + "f16": 0x0, + "f17": 0x0, + "f18": 0x0, + "f19": 0x0, + "f20": 0x0, + "f21": 0x0, + "f22": 0x0, + "f23": 0x0, + "f24": 0x0, + "f25": 0x0, + "f26": 0x0, + "f27": 0x0, + "f28": 0x0, + "f29": 0x0, + "f30": 0x0, + "f31": 0x0, + "pc": ADDR, + } + + for opcode, disassembly in CODE: + try: + uc_state = emu_with_unicorn(opcode, state) + tt_state = emu_with_triton(opcode, state) + except Exception as e: + print('[KO] %s' %(disassembly)) + print('\t%s' %(e)) + sys.exit(-1) + + if uc_state != tt_state: + print('[KO] %s' %(disassembly)) + diff_state(uc_state, tt_state) + sys.exit(-1) + + print('[OK] %s' %(disassembly)) + state = tt_state + + sys.exit(0) diff --git a/src/testers/riscv/unicorn_test_riscv64.py b/src/testers/riscv/unicorn_test_riscv64.py new file mode 100644 index 000000000..b669c38c6 --- /dev/null +++ b/src/testers/riscv/unicorn_test_riscv64.py @@ -0,0 +1,667 @@ +#!/usr/bin/env python3 +## -*- coding: utf-8 -*- + +from __future__ import print_function + +from triton import * +from unicorn import * +from unicorn.riscv_const import * +from struct import pack + +import sys +import pprint + +ADDR = 0x100000 +STACK = 0x200000 +HEAP = 0x300000 +SIZE = 5 * 1024 * 1024 + +CODE = [ + # ADDI + (b"\x93\x05\x16\x00", "addi x11, x12, #1"), + (b"\x13\x00\xe0\x00", "addi x0, x0, #0xe"), + (b"\x13\x05\x00\x00", "addi x10, x0, #0"), + (b"\x13\x00\x00\x00", "addi x0, x0, #0"), # nop + (b"\x13\x00\x00\x00", "addi x0, x0, #0"), # nop + (b"\x13\x00\x00\x00", "addi x0, x0, #0"), # nop + (b"\x93\x05\x16\x00", "addi x11, x12, #1"), + (b"\x93\x05\x06\x00", "addi x11, x12, #0"), + (b"\x13\x05\xe0\x00", "addi x10, x0, #0xe"), + (b"\x13\x03\x43\x00", "addi x6, x6, #4"), + (b"\x49\x13", "c.addi x1, x1, #1"), + (b"\x49\x13", "c.addi x6, x6, #-0xe"), + (b"\x09\x16", "c.addi x12, x12, #-30"), + (b"\x11\x01", "c.addi x2, x2, #4"), + (b"\x75\x61", "c.addi16sp x2, x2, #368"), + (b"\x40\x00", "c.addi4spn x8, x2, #4"), + (b"\x8c\x02", "c.addi4spn x10, x2, #320"), + (b"\x85\x47", "c.li x15, #1"), + (b"\x49\x4c", "c.li x24, #18"), + (b"\x09\x54", "c.li x8, #-30"), + (b"\x01\x00", "c.nop"), + (b"\x5d\x00", "c.nop 23"), + (b"\x65\x00", "c.nop 25"), + + # ADD + (b"\x33\x05\x00\x00", "add x10, x0, x0"), + (b"\x33\x86\xb0\x00", "add x12, x1, x11"), + (b"\xb3\x05\x06\x00", "add x11, x12, x0"), + (b"\xb3\x05\xc0\x00", "add x11, x0, x12"), + (b"\xbe\x95", "c.add x11, x11, x15"), + (b"\x0a\x9a", "c.add x20, x20, x2"), + (b"\x0a\x88", "c.mv x16, x2"), + (b"\xb2\x8a", "c.mv x21, x12"), + + # ADDIW + (b"\x1b\x87\xb7\x0a", "addiw x14, x15, #0xab"), + (b"\x9b\x07\x07\x00", "addiw x15, x14, #0"), # sext.w + (b"\x85\x27", "c.addiw x15, x15, #1"), + (b"\x81\x37", "c.addiw x15, x15, #-0z20"), + + # ADDW + (b"\x3b\x87\x07\x01", "addw x14, x15, x16"), + (b"\x3b\x08\x00\x01", "addw x16, x0, x16"), + (b"\xbb\x08\x05\x00", "addw x17, x10, x0"), + (b"\xb9\x9f", "c.addw x15, x15, x14"), + + # AND/I + (b"\x13\xf0\xf0\x0f", "andi x0, x1, #0xff"), + (b"\x13\x75\xf0\x0f", "andi x10, x0, #0xff"), + (b"\x93\x76\x17\x00", "andi x13, x14, #0x01"), + (b"\x93\x76\x07\x01", "andi x13, x14, #0x10"), + (b"\x49\x13", "c.andi x14, x14, #2"), + (b"\x19\x98", "c.andi x8, x8, #-26"), + (b"\xb3\x71\x52\x00", "and x3, x4, x5"), + (b"\xb3\x75\xc5\x00", "and x11, x10, x12"), + (b"\x71\x8f", "c.and x14, x14, x12"), + + # AUIPC + (b"\x17\xe5\xcd\xab", "auipc x10, #0xabcde"), + (b"\x17\x15\x00\x00", "auipc x10, #0x1"), + (b"\x17\xd9\xf1\xe2", "auipc x18, #0xf1e2d"), + (b"\x17\x10\x00\x00", "auipc x0, #0x1"), + + # SB / SH / SW / SD + (b"\x23\x0c\xa1\x00", "sb x10, 0x18(sp)"), + (b"\xa3\x0c\xa1\x00", "sb x10, 0x19(sp)"), + (b"\x23\x00\xc1\x02", "sb x12, 0x20(sp)"), + (b"\x23\x2a\xe1\x00", "sw x14, 0x14(sp)"), + (b"\x23\x20\xa1\x02", "sw x10, 0x20(sp)"), + (b"\x23\x11\xe1\x02", "sh x14, 0x22(sp)"), + (b"\x23\x10\x01\x00", "sh x0, 0(sp)"), + (b"\x23\x3c\xb1\x00", "sd x11, 0x18(sp)"), + (b"\x23\x30\xa1\x00", "sd x10, 0(sp)"), + (b"\x23\x30\xe1\x02", "sd x14, 0x20(sp)"), + (b"\x23\x12\xa1\x02", "sh x10, 0x24(sp)"), + (b"\x23\x20\xe1\x00", "sw x14, 0(sp)"), + + # LB / LH / LW / LD + (b"\x03\x35\x01\x02", "ld x10, 0x20(sp)"), + (b"\x03\x25\x01\x00", "lw x10, 0(sp)"), + (b"\x03\x07\x01\x00", "lb x14, 0(sp)"), + (b"\x03\x07\x01\x02", "lb x14, 0x20(sp)"), + (b"\x83\x15\x81\x01", "lh x11, 0x18(sp)"), + + # LBU / LHU / LWU + (b"\x03\x4a\x91\x01", "lbu x20, 0x19(sp)"), + (b"\x83\x55\x41\x02", "lhu x11, 0x24(sp)"), + (b"\x03\x66\x01\x02", "lwu x12, 0x20(sp)"), + + # Compressed load/store + (b"\x0a\x85", "c.mv x10, x2"), + (b"\x4c\x49", "c.lw x11, 0x14(x10)"), + (b"\x42\x43", "c.lwsp x6, 0x10(sp)"), + (b"\x00\x61", "c.ld x8, 0x0(x10)"), + (b"\x42\x6a", "c.ldsp x20, 0x10(sp)"), + (b"\x08\xe9", "c.sd x10, 0x10(x10)"), + (b"\x10\xf5", "c.sd x12, 0x28(x10)"), + (b"\x22\xe0", "c.sdsp x8, 0x0(sp)"), + (b"\x10\xcd", "c.sw x12, 0x18(x10)"), + (b"\x42\xc8", "c.swsp x16, 0x10(sp)"), + + #(b"\x7d\xd4", "c.beqz x8, -0x12"), + #(b"\x7d\xd5", "c.beqz x10, -0x12"), + #(b"\x7d\xf4", "c.bnez x8, -0x12"), + #(b"\x7d\xf5", "c.bnez x10, -0x12"), + + #(b"\x69\xbf", "c.j x10, 0x6ac"), + #(b"\x02\x81", "c.jr x2"), + #(b"\x02\x91", "c.jalr x2"), + + # LUI + (b"\x37\xfa\xff\xff", "lui x20, #0xfffff"), + (b"\xb7\x0a\x01\x01", "lui x21, #0x1010"), + (b"\x37\x5b\x34\x12", "lui x22, #0x12345"), + (b"\x37\x00\x00\x00", "lui x0, #0"), + (b"\x65\x67", "c.lui x14, #0x19"), + (b"\x75\x74", "c.lui x8, #0xffffd"), + + # OR/I + (b"\x93\x65\x05\x0f", "ori x11, x10, #0xf0"), + (b"\x93\x65\x76\x00", "ori x11, x12, #0x7"), + (b"\x33\x66\xb5\x00", "or x12, x10, x11"), + (b"\x51\x8f", "c.or x14, x14, x12"), + + # MUL + (b"\x33\x85\xb5\x02", "mul x10, x11, x11"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x86\xc5\x02", "mul x12, x11, x12"), + (b"\x33\x07\xa0\x02", "mul x14, x0, x10"), + (b"\x33\x17\xc6\x02", "mulh x14, x12, x12"), + (b"\xbb\x06\xb5\x02", "mulw x13, x10, x11"), + (b"\x33\x27\xc6\x02", "mulhsu x14, x12, x12"), + (b"\x33\x27\xe6\x02", "mulhsu x14, x12, x14"), + (b"\x33\x27\xe6\x02", "mulhsu x14, x12, x14"), + (b"\x33\x27\xe6\x02", "mulhsu x14, x12, x14"), + (b"\xb3\x26\xb5\x02", "mulhsu x13, x10, x11"), + (b"\x33\x37\xe6\x02", "mulhu x14, x12, x14"), + (b"\xb3\x36\xe5\x02", "mulhu x13, x10, x14"), + + # DIV/U/W + (b"\x33\x46\xa6\x02", "div x12, x12, x10"), + (b"\x33\x56\xa6\x02", "divu x12, x12, x10"), + (b"\xbb\x56\xa6\x02", "divuw x13, x12, x10"), + (b"\x3b\x47\xb6\x02", "divw x14, x12, x11"), + (b"\x3b\x40\xa6\x02", "divw x0, x12, x10"), + + # REM/U/W + (b"\xb3\x65\xa6\x02", "rem x11, x12, x10"), + (b"\xb3\x75\xa6\x02", "remu x11, x12, x10"), + (b"\xbb\x75\xa7\x02", "remuw x11, x14, x10"), + (b"\xbb\x65\xa7\x02", "remw x11, x14, x10"), + + # SUB/W + (b"\xb3\x05\xa0\x40", "sub x11, x0, x10"), + (b"\xb3\x05\xb0\x40", "sub x11, x0, x11"), # neg + (b"\xb3\x05\xa7\x40", "sub x11, x14, x10"), + (b"\x33\x00\xe7\x40", "sub x0, x14, x14"), + (b"\x89\x8d", "c.sub x11, x11, x10"), + (b"\xbb\x85\xa5\x40", "subw x11, x11, x10"), + (b"\x3b\x05\xb0\x40", "subw x10, x0, x11"), # negw + (b"\x3b\x02\x00\x40", "subw x4, x0, x0"), # negw + (b"\x01\x9c", "c.subw x8, x8, x8"), + + # XOR/I + (b"\xb3\x45\xb5\x00", "xor x11, x10, x11"), + (b"\x33\x45\xa5\x00", "xor x10, x10, x10"), + (b"\x33\x45\x00\x00", "xor x10, x0, x0"), + (b"\xb9\x8f", "c.xor x15, x15, x14"), + (b"\x93\x47\x36\x0f", "xori x15, x12, #0xf3"), + (b"\x93\x47\xe6\xff", "xori x15, x12, #-2"), + (b"\x93\x47\xf6\xff", "xori x15, x12, #-1"), # not + + # SLT + (b"\x33\x28\xb5\x00", "slt x16, x10, x11"), + (b"\x33\x28\x84\x00", "slt x16, x8, x8"), + (b"\xb3\xa0\x05\x00", "slt x1, x11, x0"), # sltz + (b"\xb3\x20\xb0\x00", "slt x1, x0, x11"), # sgtz + (b"\xb3\x20\x00\x00", "slt x1, x0, x0"), # sltz + (b"\xb3\xa0\xa0\x00", "slt x1, x1, x10"), + # SLTI + (b"\x13\xa8\x15\x00", "slti x16, x11, #1"), + (b"\x13\x28\x87\xff", "slti x16, x14, #-8"), + (b"\x13\x28\xd7\x01", "slti x16, x14, #29"), + # SLT(I)U + (b"\x93\x30\x15\x00", "sltiu x1, x10, #1"), # seqz + (b"\x13\xb8\x05\x01", "sltiu x16, x11, #0x10"), + (b"\x13\xb8\xb5\xff", "sltiu x16, x11, #-5"), + (b"\x33\xb8\xb5\x00", "sltu x16, x11, x11"), + (b"\x33\x38\xb5\x00", "sltu x16, x10, x11"), + (b"\xb3\x30\xa0\x00", "sltu x1, x0, x10"), # snez + (b"\xb3\x30\xb0\x00", "sltu x1, x0, x11"), # snez + + # SLL + (b"\xb3\x15\xb5\x00", "sll x11, x10, x11"), + (b"\x93\x10\x85\x00", "slli x1, x10, #8"), + (b"\x93\x15\xf5\x00", "slli x11, x10, #0xf"), + (b"\x12\x06", "c.slli x12, x12, #0x4"), + (b"\xbb\x15\xa5\x00", "sllw x11, x10, x10"), + (b"\xbb\x15\x05\x00", "sllw x11, x10, x0"), + (b"\x9b\x15\xb5\x00", "slliw x11, x10, #0xb"), + (b"\x1b\x15\x15\x00", "slliw x10, x10, #0x1"), + # SRA + (b"\xb3\x55\xb5\x40", "sra x11, x10, x11"), + (b"\x93\x55\x85\x40", "srai x11, x10, #8"), + (b"\x93\x55\xf5\x40", "srai x11, x10, #0xf"), + (b"\x85\x85", "c.srai x11, x11, #0x1"), + (b"\xbb\x55\xa5\x40", "sraw x11, x10, x10"), + (b"\xbb\x55\x05\x40", "sraw x11, x10, x0"), + (b"\x9b\x55\xb5\x40", "sraiw x11, x10, #0xb"), + (b"\x1b\x55\x15\x40", "sraiw x10, x10, #0x1"), + # SRL + (b"\xb3\x55\xb5\x00", "srl x11, x10, x11"), + (b"\x93\x55\x85\x00", "srli x11, x10, #8"), + (b"\x93\x55\xf5\x00", "srli x11, x10, #0xf"), + (b"\x85\x81", "c.srli x11, x11, #0x1"), + (b"\xfd\x91", "c.srli x11, x11, #0x3f"), + (b"\xbb\x55\xa5\x00", "srlw x11, x10, x10"), + (b"\xbb\x55\x05\x00", "srlw x11, x10, x0"), + (b"\x9b\x55\xb5\x00", "srliw x11, x10, #0xb"), + (b"\x1b\x55\x15\x00", "srliw x10, x10, #0x1"), + +] + +def emu_with_unicorn(opcode, istate): + # Initialize emulator in RV64 mode + mu = Uc(UC_ARCH_RISCV, UC_MODE_RISCV64) + + # map memory for this emulation + mu.mem_map(ADDR, SIZE) + + # write machine code to be emulated to memory + index = 0 + for op, _ in CODE: + mu.mem_write(ADDR+index, op) + index += len(op) + + mu.mem_write(STACK, bytes(istate['stack'])) + mu.mem_write(HEAP, bytes(istate['heap'])) + mu.reg_write(UC_RISCV_REG_X0, istate['x0']) + mu.reg_write(UC_RISCV_REG_X1, istate['x1']) + mu.reg_write(UC_RISCV_REG_X2, istate['x2']) + mu.reg_write(UC_RISCV_REG_X3, istate['x3']) + mu.reg_write(UC_RISCV_REG_X4, istate['x4']) + mu.reg_write(UC_RISCV_REG_X5, istate['x5']) + mu.reg_write(UC_RISCV_REG_X6, istate['x6']) + mu.reg_write(UC_RISCV_REG_X7, istate['x7']) + mu.reg_write(UC_RISCV_REG_X8, istate['x8']) + mu.reg_write(UC_RISCV_REG_X9, istate['x9']) + mu.reg_write(UC_RISCV_REG_X10, istate['x10']) + mu.reg_write(UC_RISCV_REG_X11, istate['x11']) + mu.reg_write(UC_RISCV_REG_X12, istate['x12']) + mu.reg_write(UC_RISCV_REG_X13, istate['x13']) + mu.reg_write(UC_RISCV_REG_X14, istate['x14']) + mu.reg_write(UC_RISCV_REG_X15, istate['x15']) + mu.reg_write(UC_RISCV_REG_X16, istate['x16']) + mu.reg_write(UC_RISCV_REG_X17, istate['x17']) + mu.reg_write(UC_RISCV_REG_X18, istate['x18']) + mu.reg_write(UC_RISCV_REG_X19, istate['x19']) + mu.reg_write(UC_RISCV_REG_X20, istate['x20']) + mu.reg_write(UC_RISCV_REG_X21, istate['x21']) + mu.reg_write(UC_RISCV_REG_X22, istate['x22']) + mu.reg_write(UC_RISCV_REG_X23, istate['x23']) + mu.reg_write(UC_RISCV_REG_X24, istate['x24']) + mu.reg_write(UC_RISCV_REG_X25, istate['x25']) + mu.reg_write(UC_RISCV_REG_X26, istate['x26']) + mu.reg_write(UC_RISCV_REG_X27, istate['x27']) + mu.reg_write(UC_RISCV_REG_X28, istate['x28']) + mu.reg_write(UC_RISCV_REG_X29, istate['x29']) + mu.reg_write(UC_RISCV_REG_X30, istate['x30']) + mu.reg_write(UC_RISCV_REG_X31, istate['x31']) + mu.reg_write(UC_RISCV_REG_F0, istate['f0']) + mu.reg_write(UC_RISCV_REG_F1, istate['f1']) + mu.reg_write(UC_RISCV_REG_F2, istate['f2']) + mu.reg_write(UC_RISCV_REG_F3, istate['f3']) + mu.reg_write(UC_RISCV_REG_F4, istate['f4']) + mu.reg_write(UC_RISCV_REG_F5, istate['f5']) + mu.reg_write(UC_RISCV_REG_F6, istate['f6']) + mu.reg_write(UC_RISCV_REG_F7, istate['f7']) + mu.reg_write(UC_RISCV_REG_F8, istate['f8']) + mu.reg_write(UC_RISCV_REG_F9, istate['f9']) + mu.reg_write(UC_RISCV_REG_F10, istate['f10']) + mu.reg_write(UC_RISCV_REG_F11, istate['f11']) + mu.reg_write(UC_RISCV_REG_F12, istate['f12']) + mu.reg_write(UC_RISCV_REG_F13, istate['f13']) + mu.reg_write(UC_RISCV_REG_F14, istate['f14']) + mu.reg_write(UC_RISCV_REG_F15, istate['f15']) + mu.reg_write(UC_RISCV_REG_F16, istate['f16']) + mu.reg_write(UC_RISCV_REG_F17, istate['f17']) + mu.reg_write(UC_RISCV_REG_F18, istate['f18']) + mu.reg_write(UC_RISCV_REG_F19, istate['f19']) + mu.reg_write(UC_RISCV_REG_F20, istate['f20']) + mu.reg_write(UC_RISCV_REG_F21, istate['f21']) + mu.reg_write(UC_RISCV_REG_F22, istate['f22']) + mu.reg_write(UC_RISCV_REG_F23, istate['f23']) + mu.reg_write(UC_RISCV_REG_F24, istate['f24']) + mu.reg_write(UC_RISCV_REG_F25, istate['f25']) + mu.reg_write(UC_RISCV_REG_F26, istate['f26']) + mu.reg_write(UC_RISCV_REG_F27, istate['f27']) + mu.reg_write(UC_RISCV_REG_F28, istate['f28']) + mu.reg_write(UC_RISCV_REG_F29, istate['f29']) + mu.reg_write(UC_RISCV_REG_F30, istate['f30']) + mu.reg_write(UC_RISCV_REG_F31, istate['f31']) + mu.reg_write(UC_RISCV_REG_PC, istate['pc']) + + # emulate code in infinite time & unlimited instructions + mu.emu_start(istate['pc'], istate['pc'] + len(opcode), 0, 1) + + ostate = { + "stack": mu.mem_read(STACK, 0x100), + "heap": mu.mem_read(HEAP, 0x100), + "x0": mu.reg_read(UC_RISCV_REG_X0), + "x1": mu.reg_read(UC_RISCV_REG_X1), + "x2": mu.reg_read(UC_RISCV_REG_X2), + "x3": mu.reg_read(UC_RISCV_REG_X3), + "x4": mu.reg_read(UC_RISCV_REG_X4), + "x5": mu.reg_read(UC_RISCV_REG_X5), + "x6": mu.reg_read(UC_RISCV_REG_X6), + "x7": mu.reg_read(UC_RISCV_REG_X7), + "x8": mu.reg_read(UC_RISCV_REG_X8), + "x9": mu.reg_read(UC_RISCV_REG_X9), + "x10": mu.reg_read(UC_RISCV_REG_X10), + "x11": mu.reg_read(UC_RISCV_REG_X11), + "x12": mu.reg_read(UC_RISCV_REG_X12), + "x13": mu.reg_read(UC_RISCV_REG_X13), + "x14": mu.reg_read(UC_RISCV_REG_X14), + "x15": mu.reg_read(UC_RISCV_REG_X15), + "x16": mu.reg_read(UC_RISCV_REG_X16), + "x17": mu.reg_read(UC_RISCV_REG_X17), + "x18": mu.reg_read(UC_RISCV_REG_X18), + "x19": mu.reg_read(UC_RISCV_REG_X19), + "x20": mu.reg_read(UC_RISCV_REG_X20), + "x21": mu.reg_read(UC_RISCV_REG_X21), + "x22": mu.reg_read(UC_RISCV_REG_X22), + "x23": mu.reg_read(UC_RISCV_REG_X23), + "x24": mu.reg_read(UC_RISCV_REG_X24), + "x25": mu.reg_read(UC_RISCV_REG_X25), + "x26": mu.reg_read(UC_RISCV_REG_X26), + "x27": mu.reg_read(UC_RISCV_REG_X27), + "x28": mu.reg_read(UC_RISCV_REG_X28), + "x29": mu.reg_read(UC_RISCV_REG_X29), + "x30": mu.reg_read(UC_RISCV_REG_X30), + "x31": mu.reg_read(UC_RISCV_REG_X31), + "f0": mu.reg_read(UC_RISCV_REG_F0), + "f1": mu.reg_read(UC_RISCV_REG_F1), + "f2": mu.reg_read(UC_RISCV_REG_F2), + "f3": mu.reg_read(UC_RISCV_REG_F3), + "f4": mu.reg_read(UC_RISCV_REG_F4), + "f5": mu.reg_read(UC_RISCV_REG_F5), + "f6": mu.reg_read(UC_RISCV_REG_F6), + "f7": mu.reg_read(UC_RISCV_REG_F7), + "f8": mu.reg_read(UC_RISCV_REG_F8), + "f9": mu.reg_read(UC_RISCV_REG_F9), + "f10": mu.reg_read(UC_RISCV_REG_F10), + "f11": mu.reg_read(UC_RISCV_REG_F11), + "f12": mu.reg_read(UC_RISCV_REG_F12), + "f13": mu.reg_read(UC_RISCV_REG_F13), + "f14": mu.reg_read(UC_RISCV_REG_F14), + "f15": mu.reg_read(UC_RISCV_REG_F15), + "f16": mu.reg_read(UC_RISCV_REG_F16), + "f17": mu.reg_read(UC_RISCV_REG_F17), + "f18": mu.reg_read(UC_RISCV_REG_F18), + "f19": mu.reg_read(UC_RISCV_REG_F19), + "f20": mu.reg_read(UC_RISCV_REG_F20), + "f21": mu.reg_read(UC_RISCV_REG_F21), + "f22": mu.reg_read(UC_RISCV_REG_F22), + "f23": mu.reg_read(UC_RISCV_REG_F23), + "f24": mu.reg_read(UC_RISCV_REG_F24), + "f25": mu.reg_read(UC_RISCV_REG_F25), + "f26": mu.reg_read(UC_RISCV_REG_F26), + "f27": mu.reg_read(UC_RISCV_REG_F27), + "f28": mu.reg_read(UC_RISCV_REG_F28), + "f29": mu.reg_read(UC_RISCV_REG_F29), + "f30": mu.reg_read(UC_RISCV_REG_F30), + "f31": mu.reg_read(UC_RISCV_REG_F31), + "pc": mu.reg_read(UC_RISCV_REG_PC), + } + return ostate + + +def emu_with_triton(opcode, istate): + ctx = TritonContext() + ctx.setArchitecture(ARCH.RV64) + + inst = Instruction(opcode) + inst.setAddress(istate['pc']) + + ctx.setConcreteMemoryAreaValue(STACK, bytes(istate['stack'])) + ctx.setConcreteMemoryAreaValue(HEAP, bytes(istate['heap'])) + ctx.setConcreteRegisterValue(ctx.registers.x0, 0) + ctx.setConcreteRegisterValue(ctx.registers.x1, istate['x1']) + ctx.setConcreteRegisterValue(ctx.registers.x2, istate['x2']) + ctx.setConcreteRegisterValue(ctx.registers.x3, istate['x3']) + ctx.setConcreteRegisterValue(ctx.registers.x4, istate['x4']) + ctx.setConcreteRegisterValue(ctx.registers.x5, istate['x5']) + ctx.setConcreteRegisterValue(ctx.registers.x6, istate['x6']) + ctx.setConcreteRegisterValue(ctx.registers.x7, istate['x7']) + ctx.setConcreteRegisterValue(ctx.registers.x8, istate['x8']) + ctx.setConcreteRegisterValue(ctx.registers.x9, istate['x9']) + ctx.setConcreteRegisterValue(ctx.registers.x10, istate['x10']) + ctx.setConcreteRegisterValue(ctx.registers.x11, istate['x11']) + ctx.setConcreteRegisterValue(ctx.registers.x12, istate['x12']) + ctx.setConcreteRegisterValue(ctx.registers.x13, istate['x13']) + ctx.setConcreteRegisterValue(ctx.registers.x14, istate['x14']) + ctx.setConcreteRegisterValue(ctx.registers.x15, istate['x15']) + ctx.setConcreteRegisterValue(ctx.registers.x16, istate['x16']) + ctx.setConcreteRegisterValue(ctx.registers.x17, istate['x17']) + ctx.setConcreteRegisterValue(ctx.registers.x18, istate['x18']) + ctx.setConcreteRegisterValue(ctx.registers.x19, istate['x19']) + ctx.setConcreteRegisterValue(ctx.registers.x20, istate['x20']) + ctx.setConcreteRegisterValue(ctx.registers.x21, istate['x21']) + ctx.setConcreteRegisterValue(ctx.registers.x22, istate['x22']) + ctx.setConcreteRegisterValue(ctx.registers.x23, istate['x23']) + ctx.setConcreteRegisterValue(ctx.registers.x24, istate['x24']) + ctx.setConcreteRegisterValue(ctx.registers.x25, istate['x25']) + ctx.setConcreteRegisterValue(ctx.registers.x26, istate['x26']) + ctx.setConcreteRegisterValue(ctx.registers.x27, istate['x27']) + ctx.setConcreteRegisterValue(ctx.registers.x28, istate['x28']) + ctx.setConcreteRegisterValue(ctx.registers.x29, istate['x29']) + ctx.setConcreteRegisterValue(ctx.registers.x30, istate['x30']) + ctx.setConcreteRegisterValue(ctx.registers.x31, istate['x31']) + ctx.setConcreteRegisterValue(ctx.registers.f0, istate['f0']) + ctx.setConcreteRegisterValue(ctx.registers.f1, istate['f1']) + ctx.setConcreteRegisterValue(ctx.registers.f2, istate['f2']) + ctx.setConcreteRegisterValue(ctx.registers.f3, istate['f3']) + ctx.setConcreteRegisterValue(ctx.registers.f4, istate['f4']) + ctx.setConcreteRegisterValue(ctx.registers.f5, istate['f5']) + ctx.setConcreteRegisterValue(ctx.registers.f6, istate['f6']) + ctx.setConcreteRegisterValue(ctx.registers.f7, istate['f7']) + ctx.setConcreteRegisterValue(ctx.registers.f8, istate['f8']) + ctx.setConcreteRegisterValue(ctx.registers.f9, istate['f9']) + ctx.setConcreteRegisterValue(ctx.registers.f10, istate['f10']) + ctx.setConcreteRegisterValue(ctx.registers.f11, istate['f11']) + ctx.setConcreteRegisterValue(ctx.registers.f12, istate['f12']) + ctx.setConcreteRegisterValue(ctx.registers.f13, istate['f13']) + ctx.setConcreteRegisterValue(ctx.registers.f14, istate['f14']) + ctx.setConcreteRegisterValue(ctx.registers.f15, istate['f15']) + ctx.setConcreteRegisterValue(ctx.registers.f16, istate['f16']) + ctx.setConcreteRegisterValue(ctx.registers.f17, istate['f17']) + ctx.setConcreteRegisterValue(ctx.registers.f18, istate['f18']) + ctx.setConcreteRegisterValue(ctx.registers.f19, istate['f19']) + ctx.setConcreteRegisterValue(ctx.registers.f20, istate['f20']) + ctx.setConcreteRegisterValue(ctx.registers.f21, istate['f21']) + ctx.setConcreteRegisterValue(ctx.registers.f22, istate['f22']) + ctx.setConcreteRegisterValue(ctx.registers.f23, istate['f23']) + ctx.setConcreteRegisterValue(ctx.registers.f24, istate['f24']) + ctx.setConcreteRegisterValue(ctx.registers.f25, istate['f25']) + ctx.setConcreteRegisterValue(ctx.registers.f26, istate['f26']) + ctx.setConcreteRegisterValue(ctx.registers.f27, istate['f27']) + ctx.setConcreteRegisterValue(ctx.registers.f28, istate['f28']) + ctx.setConcreteRegisterValue(ctx.registers.f29, istate['f29']) + ctx.setConcreteRegisterValue(ctx.registers.f30, istate['f30']) + ctx.setConcreteRegisterValue(ctx.registers.f31, istate['f31']) + ctx.setConcreteRegisterValue(ctx.registers.pc, istate['pc']) + + ctx.processing(inst) + + #print + #print(inst) + #for x in inst.getSymbolicExpressions(): + # print(x) + #print + + ostate = { + "stack": ctx.getConcreteMemoryAreaValue(STACK, 0x100), + "heap": ctx.getConcreteMemoryAreaValue(HEAP, 0x100), + + "x0": 0, + "x1": ctx.getSymbolicRegisterValue(ctx.registers.x1), + "x2": ctx.getSymbolicRegisterValue(ctx.registers.x2), + "x3": ctx.getSymbolicRegisterValue(ctx.registers.x3), + "x4": ctx.getSymbolicRegisterValue(ctx.registers.x4), + "x5": ctx.getSymbolicRegisterValue(ctx.registers.x5), + "x6": ctx.getSymbolicRegisterValue(ctx.registers.x6), + "x7": ctx.getSymbolicRegisterValue(ctx.registers.x7), + "x8": ctx.getSymbolicRegisterValue(ctx.registers.x8), + "x9": ctx.getSymbolicRegisterValue(ctx.registers.x9), + "x10": ctx.getSymbolicRegisterValue(ctx.registers.x10), + "x11": ctx.getSymbolicRegisterValue(ctx.registers.x11), + "x12": ctx.getSymbolicRegisterValue(ctx.registers.x12), + "x13": ctx.getSymbolicRegisterValue(ctx.registers.x13), + "x14": ctx.getSymbolicRegisterValue(ctx.registers.x14), + "x15": ctx.getSymbolicRegisterValue(ctx.registers.x15), + "x16": ctx.getSymbolicRegisterValue(ctx.registers.x16), + "x17": ctx.getSymbolicRegisterValue(ctx.registers.x17), + "x18": ctx.getSymbolicRegisterValue(ctx.registers.x18), + "x19": ctx.getSymbolicRegisterValue(ctx.registers.x19), + "x20": ctx.getSymbolicRegisterValue(ctx.registers.x20), + "x21": ctx.getSymbolicRegisterValue(ctx.registers.x21), + "x22": ctx.getSymbolicRegisterValue(ctx.registers.x22), + "x23": ctx.getSymbolicRegisterValue(ctx.registers.x23), + "x24": ctx.getSymbolicRegisterValue(ctx.registers.x24), + "x25": ctx.getSymbolicRegisterValue(ctx.registers.x25), + "x26": ctx.getSymbolicRegisterValue(ctx.registers.x26), + "x27": ctx.getSymbolicRegisterValue(ctx.registers.x27), + "x28": ctx.getSymbolicRegisterValue(ctx.registers.x28), + "x29": ctx.getSymbolicRegisterValue(ctx.registers.x29), + "x30": ctx.getSymbolicRegisterValue(ctx.registers.x30), + "x31": ctx.getSymbolicRegisterValue(ctx.registers.x31), + "f0": ctx.getSymbolicRegisterValue(ctx.registers.f0), + "f1": ctx.getSymbolicRegisterValue(ctx.registers.f1), + "f2": ctx.getSymbolicRegisterValue(ctx.registers.f2), + "f3": ctx.getSymbolicRegisterValue(ctx.registers.f3), + "f4": ctx.getSymbolicRegisterValue(ctx.registers.f4), + "f5": ctx.getSymbolicRegisterValue(ctx.registers.f5), + "f6": ctx.getSymbolicRegisterValue(ctx.registers.f6), + "f7": ctx.getSymbolicRegisterValue(ctx.registers.f7), + "f8": ctx.getSymbolicRegisterValue(ctx.registers.f8), + "f9": ctx.getSymbolicRegisterValue(ctx.registers.f9), + "f10": ctx.getSymbolicRegisterValue(ctx.registers.f10), + "f11": ctx.getSymbolicRegisterValue(ctx.registers.f11), + "f12": ctx.getSymbolicRegisterValue(ctx.registers.f12), + "f13": ctx.getSymbolicRegisterValue(ctx.registers.f13), + "f14": ctx.getSymbolicRegisterValue(ctx.registers.f14), + "f15": ctx.getSymbolicRegisterValue(ctx.registers.f15), + "f16": ctx.getSymbolicRegisterValue(ctx.registers.f16), + "f17": ctx.getSymbolicRegisterValue(ctx.registers.f17), + "f18": ctx.getSymbolicRegisterValue(ctx.registers.f18), + "f19": ctx.getSymbolicRegisterValue(ctx.registers.f19), + "f20": ctx.getSymbolicRegisterValue(ctx.registers.f20), + "f21": ctx.getSymbolicRegisterValue(ctx.registers.f21), + "f22": ctx.getSymbolicRegisterValue(ctx.registers.f22), + "f23": ctx.getSymbolicRegisterValue(ctx.registers.f23), + "f24": ctx.getSymbolicRegisterValue(ctx.registers.f24), + "f25": ctx.getSymbolicRegisterValue(ctx.registers.f25), + "f26": ctx.getSymbolicRegisterValue(ctx.registers.f26), + "f27": ctx.getSymbolicRegisterValue(ctx.registers.f27), + "f28": ctx.getSymbolicRegisterValue(ctx.registers.f28), + "f29": ctx.getSymbolicRegisterValue(ctx.registers.f29), + "f30": ctx.getSymbolicRegisterValue(ctx.registers.f30), + "f31": ctx.getSymbolicRegisterValue(ctx.registers.f31), + "pc": ctx.getSymbolicRegisterValue(ctx.registers.pc), + } + return ostate + + +def diff_state(state1, state2): + for k, v in list(state1.items()): + if (k == 'heap' or k == 'stack') and v != state2[k]: + print('\t%s: (UC) != (TT)' %(k)) + elif not (k == 'heap' or k == 'stack') and v != state2[k]: + print('\t%s: %#x (UC) != %#x (TT)' %(k, v, state2[k])) + return + + +if __name__ == '__main__': + # initial state + state = { + "stack": bytearray(b"".join([pack('B', 255 - i) for i in range(256)])), + "heap": bytearray(b"".join([pack('B', i) for i in range(256)])), + "x0": 0x0, + "x1": 0x0, + "x2": STACK, + "x3": 0x0, + "x4": 0x0, + "x5": 0x0, + "x6": 0x0, + "x7": 0x0, + "x8": 0x0, + "x9": 0x0, + "x10": 0x0, + "x11": 0x0, + "x12": 0x0, + "x13": 0x0, + "x14": 0x0, + "x15": 0x0, + "x16": 0x0, + "x17": 0x0, + "x18": 0x0, + "x19": 0x0, + "x20": 0x0, + "x21": 0x0, + "x22": 0x0, + "x23": 0x0, + "x24": 0x0, + "x25": 0x0, + "x26": 0x0, + "x27": 0x0, + "x28": 0x0, + "x29": 0x0, + "x30": 0x0, + "x31": 0x0, + "f0": 0x00112233445566778899aabbccddeeff, + "f1": 0xffeeddccbbaa99887766554433221100, + "f2": 0xfefedcdc5656787889892692dfeccaa0, + "f3": 0x1234567890987654321bcdffccddee01, + "f4": 0x0, + "f5": 0x0, + "f6": 0x0, + "f7": 0x0, + "f8": 0x0, + "f9": 0x0, + "f10": 0x0, + "f11": 0x0, + "f12": 0x0, + "f13": 0x0, + "f14": 0x0, + "f15": 0x0, + "f16": 0x0, + "f17": 0x0, + "f18": 0x0, + "f19": 0x0, + "f20": 0x0, + "f21": 0x0, + "f22": 0x0, + "f23": 0x0, + "f24": 0x0, + "f25": 0x0, + "f26": 0x0, + "f27": 0x0, + "f28": 0x0, + "f29": 0x0, + "f30": 0x0, + "f31": 0x0, + "pc": ADDR, + } + + for opcode, disassembly in CODE: + try: + uc_state = emu_with_unicorn(opcode, state) + tt_state = emu_with_triton(opcode, state) + except Exception as e: + print('[KO] %s' %(disassembly)) + print('\t%s' %(e)) + sys.exit(-1) + + if uc_state != tt_state: + print('[KO] %s' %(disassembly)) + diff_state(uc_state, tt_state) + sys.exit(-1) + + print('[OK] %s' %(disassembly)) + state = tt_state + + sys.exit(0)