70 lines
1.9 KiB
Python
70 lines
1.9 KiB
Python
#!/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})')
|