#!/usr/bin/env python3 # # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # from functools import cached_property from unicorn import Uc, UC_ARCH_RISCV, UC_MODE_RISCV32 from capstone import Cs from keystone import Ks from qiling.arch.arch import QlArch from qiling.arch.register import QlRegisterManager from qiling.arch import riscv_const from qiling.arch.riscv_const import * from qiling.const import QL_ARCH, QL_ENDIAN from qiling.exception import QlErrorNotImplemented class QlArchRISCV(QlArch): type = QL_ARCH.RISCV bits = 32 @cached_property def uc(self) -> Uc: return Uc(UC_ARCH_RISCV, UC_MODE_RISCV32) @cached_property def regs(self) -> QlRegisterManager: regs_map = dict( **riscv_const.reg_map, **riscv_const.reg_csr_map, **riscv_const.reg_float_map, ) pc_reg = 'pc' sp_reg = 'sp' return QlRegisterManager(self.uc, regs_map, pc_reg, sp_reg) @property def endian(self) -> QL_ENDIAN: return QL_ENDIAN.EL @cached_property def disassembler(self) -> Cs: try: from capstone import CS_ARCH_RISCV, CS_MODE_RISCV32, CS_MODE_RISCVC except ImportError: raise QlErrorNotImplemented("Capstone does not yet support riscv, upgrade to capstone 5.0") else: return Cs(CS_ARCH_RISCV, CS_MODE_RISCV32 + CS_MODE_RISCVC) @cached_property def assembler(self) -> Ks: raise QlErrorNotImplemented("Keystone does not yet support riscv") def enable_float(self): self.regs.mstatus = self.regs.mstatus | MSTATUS.FS_DIRTY def init_context(self): self.regs.pc = 0x08000000 def unicorn_exception_handler(self, ql, intno): if intno == 2: ql.log.warning(f'[{hex(self.regs.arch_pc)}] Illegal instruction') else: raise QlErrorNotImplemented(f'Unhandled interrupt number ({intno})')