From 59c8803cd8b8add8025d5fbaa1a3d8cd8791e546 Mon Sep 17 00:00:00 2001 From: dataisland Date: Wed, 3 Nov 2021 15:56:46 +0800 Subject: [PATCH 01/29] Add riscv universal register --- qiling/arch/riscv_const.py | 75 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 qiling/arch/riscv_const.py diff --git a/qiling/arch/riscv_const.py b/qiling/arch/riscv_const.py new file mode 100644 index 000000000..eb05813b2 --- /dev/null +++ b/qiling/arch/riscv_const.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +# +# Cross Platform and Multi Architecture Advanced Binary Emulation Framework +# + +from unicorn.riscv_const import * + +reg_map = { + "zero": UC_RISCV_REG_ZERO, + "ra": UC_RISCV_REG_RA, + "sp": UC_RISCV_REG_SP, + "gp": UC_RISCV_REG_GP, + "tp": UC_RISCV_REG_TP, + "t0": UC_RISCV_REG_T0, + "t1": UC_RISCV_REG_T1, + "t2": UC_RISCV_REG_T2, + "s0": UC_RISCV_REG_S0, + "fp": UC_RISCV_REG_FP, + "s1": UC_RISCV_REG_S1, + "a0": UC_RISCV_REG_A0, + "a1": UC_RISCV_REG_A1, + "a2": UC_RISCV_REG_A2, + "a3": UC_RISCV_REG_A3, + "a4": UC_RISCV_REG_A4, + "a5": UC_RISCV_REG_A5, + "a6": UC_RISCV_REG_A6, + "a7": UC_RISCV_REG_A7, + "s2": UC_RISCV_REG_S2, + "s3": UC_RISCV_REG_S3, + "s4": UC_RISCV_REG_S4, + "s5": UC_RISCV_REG_S5, + "s6": UC_RISCV_REG_S6, + "s7": UC_RISCV_REG_S7, + "s8": UC_RISCV_REG_S8, + "s9": UC_RISCV_REG_S9, + "s10": UC_RISCV_REG_S10, + "s11": UC_RISCV_REG_S11, + "t3": UC_RISCV_REG_T3, + "t4": UC_RISCV_REG_T4, + "t5": UC_RISCV_REG_T5, + "t6": UC_RISCV_REG_T6, + "ft0": UC_RISCV_REG_FT0, + "ft1": UC_RISCV_REG_FT1, + "ft2": UC_RISCV_REG_FT2, + "ft3": UC_RISCV_REG_FT3, + "ft4": UC_RISCV_REG_FT4, + "ft5": UC_RISCV_REG_FT5, + "ft6": UC_RISCV_REG_FT6, + "ft7": UC_RISCV_REG_FT7, + "fs0": UC_RISCV_REG_FS0, + "fs1": UC_RISCV_REG_FS1, + "fa0": UC_RISCV_REG_FA0, + "fa1": UC_RISCV_REG_FA1, + "fa2": UC_RISCV_REG_FA2, + "fa3": UC_RISCV_REG_FA3, + "fa4": UC_RISCV_REG_FA4, + "fa5": UC_RISCV_REG_FA5, + "fa6": UC_RISCV_REG_FA6, + "fa7": UC_RISCV_REG_FA7, + "fs2": UC_RISCV_REG_FS2, + "fs3": UC_RISCV_REG_FS3, + "fs4": UC_RISCV_REG_FS4, + "fs5": UC_RISCV_REG_FS5, + "fs6": UC_RISCV_REG_FS6, + "fs7": UC_RISCV_REG_FS7, + "fs8": UC_RISCV_REG_FS8, + "fs9": UC_RISCV_REG_FS9, + "fs10": UC_RISCV_REG_FS10, + "fs11": UC_RISCV_REG_FS11, + "ft8": UC_RISCV_REG_FT8, + "ft9": UC_RISCV_REG_FT9, + "ft10": UC_RISCV_REG_FT10, + "ft11": UC_RISCV_REG_FT11, + "pc": UC_RISCV_REG_PC, +} From 8372355c454b055ed33778683a749ab8bb1128a7 Mon Sep 17 00:00:00 2001 From: dataisland Date: Wed, 3 Nov 2021 15:57:00 +0800 Subject: [PATCH 02/29] Add riscv 32/64 bit structure --- qiling/arch/riscv.py | 33 +++++++++++++++++++++++++++++++++ qiling/arch/riscv64.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 qiling/arch/riscv.py create mode 100644 qiling/arch/riscv64.py diff --git a/qiling/arch/riscv.py b/qiling/arch/riscv.py new file mode 100644 index 000000000..3d38066d9 --- /dev/null +++ b/qiling/arch/riscv.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# +# Cross Platform and Multi Architecture Advanced Binary Emulation Framework +# + +from unicorn import Uc, UC_ARCH_RISCV, UC_MODE_RISCV32 +from capstone import Cs, CS_ARCH_RISCV, CS_MODE_RISCV32 +from keystone import Ks + +from qiling import Qiling +from qiling.arch.arch import QlArch +from qiling.arch.riscv_const import * +from qiling.exception import QlErrorNotImplemented + + +class QlArchRISCV(QlArch): + def __init__(self, ql: Qiling): + super().__init__(ql) + + self.ql.reg.expand_mapping(reg_map) + self.ql.reg.register_sp(reg_map["sp"]) + self.ql.reg.register_pc(reg_map["pc"]) + + # get initialized unicorn engine + def get_init_uc(self) -> Uc: + return Uc(UC_ARCH_RISCV, UC_MODE_RISCV32) + + def create_disassembler(self) -> Cs: + # raise QlErrorNotImplemented("Capstone does not yet support riscv") + return Cs(CS_ARCH_RISCV, CS_MODE_RISCV32) + + def create_assembler(self) -> Ks: + raise QlErrorNotImplemented("Keystone does not yet support riscv") diff --git a/qiling/arch/riscv64.py b/qiling/arch/riscv64.py new file mode 100644 index 000000000..9b2570275 --- /dev/null +++ b/qiling/arch/riscv64.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# +# Cross Platform and Multi Architecture Advanced Binary Emulation Framework +# + +from unicorn import Uc, UC_ARCH_RISCV, UC_MODE_RISCV64 +from capstone import Cs, CS_ARCH_RISCV, CS_MODE_RISCV64, CS_MODE_RISCVC +from keystone import Ks + +from qiling import Qiling +from qiling.arch.arch import QlArch +from qiling.arch.riscv_const import * +from qiling.exception import QlErrorNotImplemented + + +class QlArchRISCV64(QlArch): + def __init__(self, ql: Qiling): + super().__init__(ql) + + self.ql.reg.expand_mapping(reg_map) + self.ql.reg.register_sp(reg_map["sp"]) + self.ql.reg.register_pc(reg_map["pc"]) + + # get initialized unicorn engine + def get_init_uc(self) -> Uc: + return Uc(UC_ARCH_RISCV, UC_MODE_RISCV64) + + def create_disassembler(self) -> Cs: + # raise QlErrorNotImplemented("Capstone does not yet support riscv") + return Cs(CS_ARCH_RISCV, CS_MODE_RISCV64 + CS_MODE_RISCVC) + + def create_assembler(self) -> Ks: + raise QlErrorNotImplemented("Keystone does not yet support riscv") From f29b8286aa7d308f766a9130cfc2db39b810fd31 Mon Sep 17 00:00:00 2001 From: dataisland Date: Wed, 3 Nov 2021 15:57:16 +0800 Subject: [PATCH 03/29] Add riscv32/64 arch code --- qiling/const.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qiling/const.py b/qiling/const.py index 4132c6b73..3729a1c36 100644 --- a/qiling/const.py +++ b/qiling/const.py @@ -20,6 +20,8 @@ class QL_ARCH(IntEnum): A8086 = 107 EVM = 108 CORTEX_M = 109 + RISCV = 110 + RISCV64 = 111 class QL_OS(IntEnum): LINUX = 201 From 1d01267bdf3721ece371b731e8001b922c94bd9f Mon Sep 17 00:00:00 2001 From: dataisland Date: Wed, 3 Nov 2021 15:57:31 +0800 Subject: [PATCH 04/29] Add elf machine identifier for riscv --- qiling/utils.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/qiling/utils.py b/qiling/utils.py index 7bbea7292..1d40158e5 100644 --- a/qiling/utils.py +++ b/qiling/utils.py @@ -290,7 +290,16 @@ def ql_elf_parse_emu_env(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], elif e_machine == b"\x3E\x00": archendian = QL_ENDIAN.EL arch = QL_ARCH.X8664 + + elif e_machine == b"\xf3\x00" and elfbit == 1: + archendian = QL_ENDIAN.EL + arch = QL_ARCH.RISCV + + elif e_machine == b"\xf3\x00" and elfbit == 2: + archendian = QL_ENDIAN.EL + arch = QL_ARCH.RISCV64 + return arch, ostype, archendian def ql_macho_parse_emu_env(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], Optional[QL_ENDIAN]]: @@ -380,7 +389,7 @@ def ql_guess_emu_env(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], Opt if os.path.isfile(path) and path.endswith('.DOS_EXE'): return QL_ARCH.A8086, QL_OS.DOS, QL_ENDIAN.EL - arch, ostype, endian = ql_elf_parse_emu_env(path) + arch, ostype, endian = ql_elf_parse_emu_env(path) if arch is None or ostype is None or endian is None: arch, ostype, endian = ql_macho_parse_emu_env(path) From 715bf76b4fe059d2ee2221fdc233cbe324843294 Mon Sep 17 00:00:00 2001 From: dataisland Date: Wed, 3 Nov 2021 15:57:57 +0800 Subject: [PATCH 05/29] Add cc for riscv in linux and posix --- qiling/cc/intel.py | 12 ++++++++++++ qiling/os/linux/linux.py | 12 +++++++++++- qiling/os/posix/posix.py | 9 +++++++-- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/qiling/cc/intel.py b/qiling/cc/intel.py index c047ab781..2dc3aaaa1 100644 --- a/qiling/cc/intel.py +++ b/qiling/cc/intel.py @@ -8,6 +8,11 @@ UC_X86_REG_R9, UC_X86_REG_R10 ) +from unicorn.riscv_const import ( + UC_RISCV_REG_A0, UC_RISCV_REG_A1, UC_RISCV_REG_A2, + UC_RISCV_REG_A3, UC_RISCV_REG_A4, UC_RISCV_REG_A5, +) + from qiling import Qiling from . import QlCommonBaseCC @@ -83,6 +88,13 @@ class macosx64(QlIntel64): _argregs = (UC_X86_REG_RDI, UC_X86_REG_RSI, UC_X86_REG_RDX, UC_X86_REG_RCX, UC_X86_REG_R8, UC_X86_REG_R9) + (None, ) * 10 +class riscv(QlIntel64): + """Default calling convention for RISCV + First 6 arguments are passed in regs, the rest are passed on the stack. + """ + + _argregs = (UC_RISCV_REG_A0, UC_RISCV_REG_A1, UC_RISCV_REG_A2, UC_RISCV_REG_A3, UC_RISCV_REG_A4, UC_RISCV_REG_A5) + class cdecl(QlIntel32): """Calling convention used by all operating systems (x86). All arguments are passed on the stack. diff --git a/qiling/os/linux/linux.py b/qiling/os/linux/linux.py index a6aff18d4..43cc0b191 100644 --- a/qiling/os/linux/linux.py +++ b/qiling/os/linux/linux.py @@ -31,7 +31,9 @@ def __init__(self, ql: Qiling): QL_ARCH.X8664 : intel.amd64, QL_ARCH.ARM : arm.aarch32, QL_ARCH.ARM64 : arm.aarch64, - QL_ARCH.MIPS : mips.mipso32 + QL_ARCH.MIPS : mips.mipso32, + QL_ARCH.RISCV : intel.riscv, + QL_ARCH.RISCV64: intel.riscv, }[ql.archtype](ql) self.fcall = QlFunctionCall(ql, cc) @@ -84,6 +86,14 @@ def load(self): # Keep test for _cc #self.ql.hook_insn(hook_posix_api, UC_X86_INS_SYSCALL) self.thread_class = thread.QlLinuxX8664Thread + + elif self.ql.archtype == QL_ARCH.RISCV: + self.ql.hook_intno(self.hook_syscall, 8) + self.thread_class = None + + elif self.ql.archtype == QL_ARCH.RISCV64: + self.ql.hook_intno(self.hook_syscall, 8) + self.thread_class = None for i in range(NR_OPEN): if hasattr(self.fd[i], 'close_on_exec') and \ diff --git a/qiling/os/posix/posix.py b/qiling/os/posix/posix.py index d04049e25..44f416d61 100644 --- a/qiling/os/posix/posix.py +++ b/qiling/os/posix/posix.py @@ -10,6 +10,7 @@ from unicorn.arm_const import UC_ARM_REG_R7 from unicorn.mips_const import UC_MIPS_REG_V0 from unicorn.x86_const import UC_X86_REG_EAX, UC_X86_REG_RAX +from unicorn.riscv_const import UC_RISCV_REG_A7 from qiling import Qiling from qiling.cc import QlCC, intel, arm, mips @@ -77,7 +78,9 @@ def __init__(self, ql: Qiling): QL_ARCH.ARM : UC_ARM_REG_R7, QL_ARCH.MIPS : UC_MIPS_REG_V0, QL_ARCH.X86 : UC_X86_REG_EAX, - QL_ARCH.X8664: UC_X86_REG_RAX + QL_ARCH.X8664: UC_X86_REG_RAX, + QL_ARCH.RISCV: UC_RISCV_REG_A7, + QL_ARCH.RISCV64: UC_RISCV_REG_A7, }[self.ql.archtype] # handle a special case @@ -92,7 +95,9 @@ def __init__(self, ql: Qiling): QL_ARCH.ARM : aarch32, QL_ARCH.MIPS : mipso32, QL_ARCH.X86 : intel32, - QL_ARCH.X8664: intel64 + QL_ARCH.X8664: intel64, + QL_ARCH.RISCV: intel.riscv, + QL_ARCH.RISCV64: intel.riscv, }[self.ql.archtype](ql) self._fd = QlFileDes([0] * NR_OPEN) From 01b2f4658bedd0d3262de5d4a42080ee07e9177d Mon Sep 17 00:00:00 2001 From: dataisland Date: Wed, 3 Nov 2021 15:58:09 +0800 Subject: [PATCH 06/29] Enable the riscv function hook --- qiling/os/linux/function_hook.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/qiling/os/linux/function_hook.py b/qiling/os/linux/function_hook.py index bdf69f85f..a030af8b3 100644 --- a/qiling/os/linux/function_hook.py +++ b/qiling/os/linux/function_hook.py @@ -598,6 +598,24 @@ def __init__(self, ql, phoff, phnum, phentsize, load_base, hook_mem): ins = b'\x90' self.add_function_hook = self.add_function_hook_relocation + elif self.ql.archtype== QL_ARCH.RISCV: + # TODO: specific other parameters + # self.GLOB_DAT = 0 + # self.JMP_SLOT = 0 + + # ADDI x0, x0, 0 + ins = b'\x00\x01' + # self.add_function_hook = self.add_function_hook_relocation + + elif self.ql.archtype== QL_ARCH.RISCV64: + # TODO: specific other parameters + # self.GLOB_DAT = 0 + # self.JMP_SLOT = 0 + + # ADDI x0, x0, 0 + ins = b'\x00\x01' + # self.add_function_hook = self.add_function_hook_relocation + self._parse() if self.rel != None: self.show_relocation(self.rel) From f75cf9d5716d3460b4bf04dd6724114029dbd5bf Mon Sep 17 00:00:00 2001 From: dataisland Date: Wed, 3 Nov 2021 16:00:07 +0800 Subject: [PATCH 07/29] Append riscv in arch bit array --- qiling/const.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qiling/const.py b/qiling/const.py index 3729a1c36..1c1ffb8fe 100644 --- a/qiling/const.py +++ b/qiling/const.py @@ -56,8 +56,8 @@ class QL_INTERCEPT(IntEnum): QL_ARCH_ENDIAN = (QL_ARCH.MIPS, QL_ARCH.ARM) QL_ARCH_1BIT = (QL_ARCH.EVM,) QL_ARCH_16BIT = (QL_ARCH.A8086,) -QL_ARCH_32BIT = (QL_ARCH.ARM, QL_ARCH.ARM_THUMB, QL_ARCH.MIPS, QL_ARCH.X86, QL_ARCH.CORTEX_M) -QL_ARCH_64BIT = (QL_ARCH.ARM64, QL_ARCH.X8664) +QL_ARCH_32BIT = (QL_ARCH.ARM, QL_ARCH.ARM_THUMB, QL_ARCH.MIPS, QL_ARCH.X86, QL_ARCH.CORTEX_M, QL_ARCH.RISCV) +QL_ARCH_64BIT = (QL_ARCH.ARM64, QL_ARCH.X8664, QL_ARCH.RISCV64) QL_OS_NONPID = (QL_OS.DOS, QL_OS.UEFI) QL_ARCH_BAREMETAL = (QL_ARCH.CORTEX_M,) From a7baec38be5d43e259b9640e2f1adc256ad1856e Mon Sep 17 00:00:00 2001 From: dataisland Date: Wed, 3 Nov 2021 16:00:19 +0800 Subject: [PATCH 08/29] Enable syscall in riscv --- qiling/os/linux/map_syscall.py | 604 ++++++++++++++++++++++++++++++++- 1 file changed, 603 insertions(+), 1 deletion(-) diff --git a/qiling/os/linux/map_syscall.py b/qiling/os/linux/map_syscall.py index 7c1fcfabe..fbef39e9b 100644 --- a/qiling/os/linux/map_syscall.py +++ b/qiling/os/linux/map_syscall.py @@ -18,7 +18,9 @@ def map_syscall(ql, syscall_num): QL_ARCH.X8664: x8664_syscall_table, QL_ARCH.X86: x86_syscall_table, QL_ARCH.MIPS: mips_syscall_table, - }.get(ql.archtype, None) + QL_ARCH.RISCV: riscv32_syscall_table, + QL_ARCH.RISCV64: riscv64_syscall_table, + }.get(ql.archtype, None) return f'{SYSCALL_PREF}{syscalls_table[syscall_num]}' @@ -1928,3 +1930,603 @@ def map_syscall(ql, syscall_num): 4446: "landlock_restrict_self", 4448: "process_mrelease", } + +riscv32_syscall_table = { + 0: "io_setup", + 1: "io_destroy", + 2: "io_submit", + 3: "io_cancel", + 5: "setxattr", + 6: "lsetxattr", + 7: "fsetxattr", + 8: "getxattr", + 9: "lgetxattr", + 10: "fgetxattr", + 11: "listxattr", + 12: "llistxattr", + 13: "flistxattr", + 14: "removexattr", + 15: "lremovexattr", + 16: "fremovexattr", + 17: "getcwd", + 18: "lookup_dcookie", + 19: "eventfd2", + 20: "epoll_create1", + 21: "epoll_ctl", + 22: "epoll_pwait", + 23: "dup", + 24: "dup3", + 25: "fcntl64", + 26: "inotify_init1", + 27: "inotify_add_watch", + 28: "inotify_rm_watch", + 29: "ioctl", + 30: "ioprio_set", + 31: "ioprio_get", + 32: "flock", + 33: "mknodat", + 34: "mkdirat", + 35: "unlinkat", + 36: "symlinkat", + 37: "linkat", + 39: "umount2", + 40: "mount", + 41: "pivot_root", + 42: "nfsservctl", + 43: "statfs64", + 44: "fstatfs64", + 45: "truncate64", + 46: "ftruncate64", + 47: "fallocate", + 48: "faccessat", + 49: "chdir", + 50: "fchdir", + 51: "chroot", + 52: "fchmod", + 53: "fchmodat", + 54: "fchownat", + 55: "fchown", + 56: "openat", + 57: "close", + 58: "vhangup", + 59: "pipe2", + 60: "quotactl", + 61: "getdents64", + 63: "read", + 64: "write", + 65: "readv", + 66: "writev", + 67: "pread64", + 68: "pwrite64", + 69: "preadv", + 70: "pwritev", + 71: "sendfile64", + 74: "signalfd4", + 75: "vmsplice", + 76: "splice", + 77: "tee", + 78: "readlinkat", + 81: "sync", + 82: "fsync", + 83: "fdatasync", + 84: "sync_file_range", + 85: "timerfd_create", + 89: "acct", + 90: "capget", + 91: "capset", + 92: "personality", + 93: "exit", + 94: "exit_group", + 95: "waitid", + 96: "set_tid_address", + 97: "unshare", + 99: "set_robust_list", + 100: "get_robust_list", + 102: "getitimer", + 103: "setitimer", + 104: "kexec_load", + 105: "init_module", + 106: "delete_module", + 107: "timer_create", + 109: "timer_getoverrun", + 111: "timer_delete", + 116: "syslog", + 117: "ptrace", + 118: "sched_setparam", + 119: "sched_setscheduler", + 120: "sched_getscheduler", + 121: "sched_getparam", + 122: "sched_setaffinity", + 123: "sched_getaffinity", + 124: "sched_yield", + 125: "sched_get_priority_max", + 126: "sched_get_priority_min", + 128: "restart_syscall", + 129: "kill", + 130: "tkill", + 131: "tgkill", + 132: "sigaltstack", + 133: "rt_sigsuspend", + 134: "rt_sigaction", + 135: "rt_sigprocmask", + 136: "rt_sigpending", + 138: "rt_sigqueueinfo", + 139: "rt_sigreturn", + 140: "setpriority", + 141: "getpriority", + 142: "reboot", + 143: "setregid", + 144: "setgid", + 145: "setreuid", + 146: "setuid", + 147: "setresuid", + 148: "getresuid", + 149: "setresgid", + 150: "getresgid", + 151: "setfsuid", + 152: "setfsgid", + 153: "times", + 154: "setpgid", + 155: "getpgid", + 156: "getsid", + 157: "setsid", + 158: "getgroups", + 159: "setgroups", + 160: "uname", + 161: "sethostname", + 162: "setdomainname", + 165: "getrusage", + 166: "umask", + 167: "prctl", + 168: "getcpu", + 172: "getpid", + 173: "getppid", + 174: "getuid", + 175: "geteuid", + 176: "getgid", + 177: "getegid", + 178: "gettid", + 179: "sysinfo", + 180: "mq_open", + 181: "mq_unlink", + 184: "mq_notify", + 185: "mq_getsetattr", + 186: "msgget", + 187: "msgctl", + 188: "msgrcv", + 189: "msgsnd", + 190: "semget", + 191: "semctl", + 193: "semop", + 194: "shmget", + 195: "shmctl", + 196: "shmat", + 197: "shmdt", + 198: "socket", + 199: "socketpair", + 200: "bind", + 201: "listen", + 202: "accept", + 203: "connect", + 204: "getsockname", + 205: "getpeername", + 206: "sendto", + 207: "recvfrom", + 208: "setsockopt", + 209: "getsockopt", + 210: "shutdown", + 211: "sendmsg", + 212: "recvmsg", + 213: "readahead", + 214: "brk", + 215: "munmap", + 216: "mremap", + 217: "add_key", + 218: "request_key", + 219: "keyctl", + 220: "clone", + 221: "execve", + 222: "mmap2", + 223: "fadvise64_64", + 224: "swapon", + 225: "swapoff", + 226: "mprotect", + 227: "msync", + 228: "mlock", + 229: "munlock", + 230: "mlockall", + 231: "munlockall", + 232: "mincore", + 233: "madvise", + 234: "remap_file_pages", + 235: "mbind", + 236: "get_mempolicy", + 237: "set_mempolicy", + 238: "migrate_pages", + 239: "move_pages", + 240: "rt_tgsigqueueinfo", + 241: "perf_event_open", + 242: "accept4", + 259: "riscv_flush_icache", + 261: "prlimit64", + 262: "fanotify_init", + 263: "fanotify_mark", + 264: "name_to_handle_at", + 265: "open_by_handle_at", + 267: "syncfs", + 268: "setns", + 269: "sendmmsg", + 270: "process_vm_readv", + 271: "process_vm_writev", + 272: "kcmp", + 273: "finit_module", + 274: "sched_setattr", + 275: "sched_getattr", + 276: "renameat2", + 277: "seccomp", + 278: "getrandom", + 279: "memfd_create", + 280: "bpf", + 281: "execveat", + 282: "userfaultfd", + 283: "membarrier", + 284: "mlock2", + 285: "copy_file_range", + 286: "preadv2", + 287: "pwritev2", + 288: "pkey_mprotect", + 289: "pkey_alloc", + 290: "pkey_free", + 291: "statx", + 293: "rseq", + 294: "kexec_file_load", + 403: "clock_gettime64", + 404: "clock_settime64", + 405: "clock_adjtime64", + 406: "clock_getres_time64", + 407: "clock_nanosleep_time64", + 408: "timer_gettime64", + 409: "timer_settime64", + 410: "timerfd_gettime64", + 411: "timerfd_settime64", + 412: "utimensat_time64", + 413: "pselect6_time64", + 414: "ppoll_time64", + 416: "io_pgetevents_time64", + 417: "recvmmsg_time64", + 418: "mq_timedsend_time64", + 419: "mq_timedreceive_time64", + 420: "semtimedop_time64", + 421: "rt_sigtimedwait_time64", + 422: "futex_time64", + 423: "sched_rr_get_interval_time64", + 424: "pidfd_send_signal", + 425: "io_uring_setup", + 426: "io_uring_enter", + 427: "io_uring_register", + 428: "open_tree", + 429: "move_mount", + 430: "fsopen", + 431: "fsconfig", + 432: "fsmount", + 433: "fspick", + 434: "pidfd_open", + 436: "close_range", + 437: "openat2", + 438: "pidfd_getfd", + 439: "faccessat2", + 440: "process_madvise", + 441: "epoll_pwait2", + 442: "mount_setattr", + 443: "quotactl_fd", + 444: "landlock_create_ruleset", + 445: "landlock_add_rule", + 446: "landlock_restrict_self", + 448: "process_mrelease", +} + +riscv64_syscall_table = { + 0: "io_setup", + 1: "io_destroy", + 2: "io_submit", + 3: "io_cancel", + 4: "io_getevents", + 5: "setxattr", + 6: "lsetxattr", + 7: "fsetxattr", + 8: "getxattr", + 9: "lgetxattr", + 10: "fgetxattr", + 11: "listxattr", + 12: "llistxattr", + 13: "flistxattr", + 14: "removexattr", + 15: "lremovexattr", + 16: "fremovexattr", + 17: "getcwd", + 18: "lookup_dcookie", + 19: "eventfd2", + 20: "epoll_create1", + 21: "epoll_ctl", + 22: "epoll_pwait", + 23: "dup", + 24: "dup3", + 25: "fcntl", + 26: "inotify_init1", + 27: "inotify_add_watch", + 28: "inotify_rm_watch", + 29: "ioctl", + 30: "ioprio_set", + 31: "ioprio_get", + 32: "flock", + 33: "mknodat", + 34: "mkdirat", + 35: "unlinkat", + 36: "symlinkat", + 37: "linkat", + 39: "umount2", + 40: "mount", + 41: "pivot_root", + 42: "nfsservctl", + 43: "statfs", + 44: "fstatfs", + 45: "truncate", + 46: "ftruncate", + 47: "fallocate", + 48: "faccessat", + 49: "chdir", + 50: "fchdir", + 51: "chroot", + 52: "fchmod", + 53: "fchmodat", + 54: "fchownat", + 55: "fchown", + 56: "openat", + 57: "close", + 58: "vhangup", + 59: "pipe2", + 60: "quotactl", + 61: "getdents64", + 62: "lseek", + 63: "read", + 64: "write", + 65: "readv", + 66: "writev", + 67: "pread64", + 68: "pwrite64", + 69: "preadv", + 70: "pwritev", + 71: "sendfile", + 72: "pselect6", + 73: "ppoll", + 74: "signalfd4", + 75: "vmsplice", + 76: "splice", + 77: "tee", + 78: "readlinkat", + 79: "newfstatat", + 80: "fstat", + 81: "sync", + 82: "fsync", + 83: "fdatasync", + 84: "sync_file_range", + 85: "timerfd_create", + 86: "timerfd_settime", + 87: "timerfd_gettime", + 88: "utimensat", + 89: "acct", + 90: "capget", + 91: "capset", + 92: "personality", + 93: "exit", + 94: "exit_group", + 95: "waitid", + 96: "set_tid_address", + 97: "unshare", + 98: "futex", + 99: "set_robust_list", + 100: "get_robust_list", + 101: "nanosleep", + 102: "getitimer", + 103: "setitimer", + 104: "kexec_load", + 105: "init_module", + 106: "delete_module", + 107: "timer_create", + 108: "timer_gettime", + 109: "timer_getoverrun", + 110: "timer_settime", + 111: "timer_delete", + 112: "clock_settime", + 113: "clock_gettime", + 114: "clock_getres", + 115: "clock_nanosleep", + 116: "syslog", + 117: "ptrace", + 118: "sched_setparam", + 119: "sched_setscheduler", + 120: "sched_getscheduler", + 121: "sched_getparam", + 122: "sched_setaffinity", + 123: "sched_getaffinity", + 124: "sched_yield", + 125: "sched_get_priority_max", + 126: "sched_get_priority_min", + 127: "sched_rr_get_interval", + 128: "restart_syscall", + 129: "kill", + 130: "tkill", + 131: "tgkill", + 132: "sigaltstack", + 133: "rt_sigsuspend", + 134: "rt_sigaction", + 135: "rt_sigprocmask", + 136: "rt_sigpending", + 137: "rt_sigtimedwait", + 138: "rt_sigqueueinfo", + 139: "rt_sigreturn", + 140: "setpriority", + 141: "getpriority", + 142: "reboot", + 143: "setregid", + 144: "setgid", + 145: "setreuid", + 146: "setuid", + 147: "setresuid", + 148: "getresuid", + 149: "setresgid", + 150: "getresgid", + 151: "setfsuid", + 152: "setfsgid", + 153: "times", + 154: "setpgid", + 155: "getpgid", + 156: "getsid", + 157: "setsid", + 158: "getgroups", + 159: "setgroups", + 160: "uname", + 161: "sethostname", + 162: "setdomainname", + 163: "getrlimit", + 164: "setrlimit", + 165: "getrusage", + 166: "umask", + 167: "prctl", + 168: "getcpu", + 169: "gettimeofday", + 170: "settimeofday", + 171: "adjtimex", + 172: "getpid", + 173: "getppid", + 174: "getuid", + 175: "geteuid", + 176: "getgid", + 177: "getegid", + 178: "gettid", + 179: "sysinfo", + 180: "mq_open", + 181: "mq_unlink", + 182: "mq_timedsend", + 183: "mq_timedreceive", + 184: "mq_notify", + 185: "mq_getsetattr", + 186: "msgget", + 187: "msgctl", + 188: "msgrcv", + 189: "msgsnd", + 190: "semget", + 191: "semctl", + 192: "semtimedop", + 193: "semop", + 194: "shmget", + 195: "shmctl", + 196: "shmat", + 197: "shmdt", + 198: "socket", + 199: "socketpair", + 200: "bind", + 201: "listen", + 202: "accept", + 203: "connect", + 204: "getsockname", + 205: "getpeername", + 206: "sendto", + 207: "recvfrom", + 208: "setsockopt", + 209: "getsockopt", + 210: "shutdown", + 211: "sendmsg", + 212: "recvmsg", + 213: "readahead", + 214: "brk", + 215: "munmap", + 216: "mremap", + 217: "add_key", + 218: "request_key", + 219: "keyctl", + 220: "clone", + 221: "execve", + 222: "mmap", + 223: "fadvise64", + 224: "swapon", + 225: "swapoff", + 226: "mprotect", + 227: "msync", + 228: "mlock", + 229: "munlock", + 230: "mlockall", + 231: "munlockall", + 232: "mincore", + 233: "madvise", + 234: "remap_file_pages", + 235: "mbind", + 236: "get_mempolicy", + 237: "set_mempolicy", + 238: "migrate_pages", + 239: "move_pages", + 240: "rt_tgsigqueueinfo", + 241: "perf_event_open", + 242: "accept4", + 243: "recvmmsg", + 259: "riscv_flush_icache", + 260: "wait4", + 261: "prlimit64", + 262: "fanotify_init", + 263: "fanotify_mark", + 264: "name_to_handle_at", + 265: "open_by_handle_at", + 266: "clock_adjtime", + 267: "syncfs", + 268: "setns", + 269: "sendmmsg", + 270: "process_vm_readv", + 271: "process_vm_writev", + 272: "kcmp", + 273: "finit_module", + 274: "sched_setattr", + 275: "sched_getattr", + 276: "renameat2", + 277: "seccomp", + 278: "getrandom", + 279: "memfd_create", + 280: "bpf", + 281: "execveat", + 282: "userfaultfd", + 283: "membarrier", + 284: "mlock2", + 285: "copy_file_range", + 286: "preadv2", + 287: "pwritev2", + 288: "pkey_mprotect", + 289: "pkey_alloc", + 290: "pkey_free", + 291: "statx", + 292: "io_pgetevents", + 293: "rseq", + 294: "kexec_file_load", + 424: "pidfd_send_signal", + 425: "io_uring_setup", + 426: "io_uring_enter", + 427: "io_uring_register", + 428: "open_tree", + 429: "move_mount", + 430: "fsopen", + 431: "fsconfig", + 432: "fsmount", + 433: "fspick", + 434: "pidfd_open", + 435: "clone3", + 436: "close_range", + 437: "openat2", + 438: "pidfd_getfd", + 439: "faccessat2", + 440: "process_madvise", + 441: "epoll_pwait2", + 442: "mount_setattr", + 443: "quotactl_fd", + 444: "landlock_create_ruleset", + 445: "landlock_add_rule", + 446: "landlock_restrict_self", + 448: "process_mrelease", +} From 0dbddfed6f1ca8eff91eea456aedd4710c1e7fd7 Mon Sep 17 00:00:00 2001 From: dataisland Date: Wed, 3 Nov 2021 16:07:49 +0800 Subject: [PATCH 09/29] Add riscv helloworld example source code --- examples/src/linux/hello_riscv.s | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 examples/src/linux/hello_riscv.s diff --git a/examples/src/linux/hello_riscv.s b/examples/src/linux/hello_riscv.s new file mode 100644 index 000000000..fc4668ff6 --- /dev/null +++ b/examples/src/linux/hello_riscv.s @@ -0,0 +1,16 @@ +# riscv${bit}-unknown-elf-as hello_riscv.s -o hello_riscv.o +# riscv${bit}-unknown-elf-ld hello_riscv.o -o hello_riscv + +.global _start + +_start: addi a0, x0, 1 + la a1, helloriscv + addi a2, x0, 13 + addi a7, x0, 64 + ecall + addi a0, x0, 0 + addi a7, x0, 93 + ecall + +.data +helloriscv: .ascii "Hello RISCV!\n" From ab04e0fe7eec78d5a550c10b9659d8c4e903759d Mon Sep 17 00:00:00 2001 From: dataisland Date: Thu, 4 Nov 2021 09:12:28 +0800 Subject: [PATCH 10/29] Fix the capstone import --- qiling/arch/riscv.py | 9 ++++++--- qiling/arch/riscv64.py | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/qiling/arch/riscv.py b/qiling/arch/riscv.py index 3d38066d9..ab0b29ec7 100644 --- a/qiling/arch/riscv.py +++ b/qiling/arch/riscv.py @@ -4,7 +4,7 @@ # from unicorn import Uc, UC_ARCH_RISCV, UC_MODE_RISCV32 -from capstone import Cs, CS_ARCH_RISCV, CS_MODE_RISCV32 +from capstone import Cs from keystone import Ks from qiling import Qiling @@ -26,8 +26,11 @@ def get_init_uc(self) -> Uc: return Uc(UC_ARCH_RISCV, UC_MODE_RISCV32) def create_disassembler(self) -> Cs: - # raise QlErrorNotImplemented("Capstone does not yet support riscv") - return Cs(CS_ARCH_RISCV, CS_MODE_RISCV32) + try: + from capstone import CS_ARCH_RISCV, CS_MODE_RISCV32 + return Cs(CS_ARCH_RISCV, CS_MODE_RISCV32) + except ImportError: + raise QlErrorNotImplemented("Capstone does not yet support riscv, upgrade to capstone 5.0") def create_assembler(self) -> Ks: raise QlErrorNotImplemented("Keystone does not yet support riscv") diff --git a/qiling/arch/riscv64.py b/qiling/arch/riscv64.py index 9b2570275..8430b7960 100644 --- a/qiling/arch/riscv64.py +++ b/qiling/arch/riscv64.py @@ -4,7 +4,7 @@ # from unicorn import Uc, UC_ARCH_RISCV, UC_MODE_RISCV64 -from capstone import Cs, CS_ARCH_RISCV, CS_MODE_RISCV64, CS_MODE_RISCVC +from capstone import Cs from keystone import Ks from qiling import Qiling @@ -26,8 +26,11 @@ def get_init_uc(self) -> Uc: return Uc(UC_ARCH_RISCV, UC_MODE_RISCV64) def create_disassembler(self) -> Cs: - # raise QlErrorNotImplemented("Capstone does not yet support riscv") - return Cs(CS_ARCH_RISCV, CS_MODE_RISCV64 + CS_MODE_RISCVC) + try: + from capstone import CS_ARCH_RISCV, CS_MODE_RISCV64, CS_MODE_RISCVC + return Cs(CS_ARCH_RISCV, CS_MODE_RISCV32) + except ImportError: + raise QlErrorNotImplemented("Capstone does not yet support riscv, upgrade to capstone 5.0") def create_assembler(self) -> Ks: raise QlErrorNotImplemented("Keystone does not yet support riscv") From 059a47be5b8324a47b7adc2a822d656e86b8aec5 Mon Sep 17 00:00:00 2001 From: dataisland Date: Thu, 4 Nov 2021 10:33:22 +0800 Subject: [PATCH 11/29] Fix riscv64 capstone mode --- qiling/arch/riscv64.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiling/arch/riscv64.py b/qiling/arch/riscv64.py index 8430b7960..51254d87f 100644 --- a/qiling/arch/riscv64.py +++ b/qiling/arch/riscv64.py @@ -28,7 +28,7 @@ def get_init_uc(self) -> Uc: def create_disassembler(self) -> Cs: try: from capstone import CS_ARCH_RISCV, CS_MODE_RISCV64, CS_MODE_RISCVC - return Cs(CS_ARCH_RISCV, CS_MODE_RISCV32) + return Cs(CS_ARCH_RISCV, CS_MODE_RISCV64 + CS_MODE_RISCVC) except ImportError: raise QlErrorNotImplemented("Capstone does not yet support riscv, upgrade to capstone 5.0") From 619ca43446fa7096c0db3d4789ff59c1f344b66d Mon Sep 17 00:00:00 2001 From: dataisland Date: Thu, 4 Nov 2021 12:37:33 +0800 Subject: [PATCH 12/29] Move the riscv cc to new file --- qiling/cc/intel.py | 12 ------------ qiling/cc/riscv.py | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 qiling/cc/riscv.py diff --git a/qiling/cc/intel.py b/qiling/cc/intel.py index 2dc3aaaa1..c047ab781 100644 --- a/qiling/cc/intel.py +++ b/qiling/cc/intel.py @@ -8,11 +8,6 @@ UC_X86_REG_R9, UC_X86_REG_R10 ) -from unicorn.riscv_const import ( - UC_RISCV_REG_A0, UC_RISCV_REG_A1, UC_RISCV_REG_A2, - UC_RISCV_REG_A3, UC_RISCV_REG_A4, UC_RISCV_REG_A5, -) - from qiling import Qiling from . import QlCommonBaseCC @@ -88,13 +83,6 @@ class macosx64(QlIntel64): _argregs = (UC_X86_REG_RDI, UC_X86_REG_RSI, UC_X86_REG_RDX, UC_X86_REG_RCX, UC_X86_REG_R8, UC_X86_REG_R9) + (None, ) * 10 -class riscv(QlIntel64): - """Default calling convention for RISCV - First 6 arguments are passed in regs, the rest are passed on the stack. - """ - - _argregs = (UC_RISCV_REG_A0, UC_RISCV_REG_A1, UC_RISCV_REG_A2, UC_RISCV_REG_A3, UC_RISCV_REG_A4, UC_RISCV_REG_A5) - class cdecl(QlIntel32): """Calling convention used by all operating systems (x86). All arguments are passed on the stack. diff --git a/qiling/cc/riscv.py b/qiling/cc/riscv.py new file mode 100644 index 000000000..e768f6c4d --- /dev/null +++ b/qiling/cc/riscv.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Cross Platform and Multi Architecture Advanced Binary Emulation Framework + +from qiling import Qiling +from . import QlCommonBaseCC + +from unicorn.riscv_const import ( + UC_RISCV_REG_A0, UC_RISCV_REG_A1, UC_RISCV_REG_A2, + UC_RISCV_REG_A3, UC_RISCV_REG_A4, UC_RISCV_REG_A5, +) + + +class riscv(QlCommonBaseCC): + """Default calling convention for RISCV + First 6 arguments are passed in regs, the rest are passed on the stack. + """ + + _argregs = (UC_RISCV_REG_A0, UC_RISCV_REG_A1, UC_RISCV_REG_A2, UC_RISCV_REG_A3, UC_RISCV_REG_A4, UC_RISCV_REG_A5) + (None, ) * 10 + + def __init__(self, ql: Qiling): + super().__init__(ql, UC_RISCV_REG_A0) + + @staticmethod + def getNumSlots(argbits: int): + return 1 \ No newline at end of file From 8699c5239a4473a264bb2b2ff26cfdb8119b651d Mon Sep 17 00:00:00 2001 From: dataisland Date: Thu, 4 Nov 2021 12:37:52 +0800 Subject: [PATCH 13/29] Fix the riscv syscall cc --- qiling/os/linux/linux.py | 6 +++--- qiling/os/posix/posix.py | 12 +++++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/qiling/os/linux/linux.py b/qiling/os/linux/linux.py index 43cc0b191..bac4aba58 100644 --- a/qiling/os/linux/linux.py +++ b/qiling/os/linux/linux.py @@ -9,7 +9,7 @@ from qiling import Qiling from qiling.arch.x86_const import UC_X86_INS_SYSCALL from qiling.arch.x86 import GDTManager, ql_x8664_set_gs, ql_x86_register_cs, ql_x86_register_ds_ss_es -from qiling.cc import QlCC, intel, arm, mips +from qiling.cc import QlCC, intel, arm, mips, riscv from qiling.const import QL_ARCH, QL_INTERCEPT from qiling.os.fcall import QlFunctionCall from qiling.os.const import * @@ -32,8 +32,8 @@ def __init__(self, ql: Qiling): QL_ARCH.ARM : arm.aarch32, QL_ARCH.ARM64 : arm.aarch64, QL_ARCH.MIPS : mips.mipso32, - QL_ARCH.RISCV : intel.riscv, - QL_ARCH.RISCV64: intel.riscv, + QL_ARCH.RISCV : riscv.riscv, + QL_ARCH.RISCV64: riscv.riscv, }[ql.archtype](ql) self.fcall = QlFunctionCall(ql, cc) diff --git a/qiling/os/posix/posix.py b/qiling/os/posix/posix.py index 44f416d61..d5787cbab 100644 --- a/qiling/os/posix/posix.py +++ b/qiling/os/posix/posix.py @@ -13,7 +13,7 @@ from unicorn.riscv_const import UC_RISCV_REG_A7 from qiling import Qiling -from qiling.cc import QlCC, intel, arm, mips +from qiling.cc import QlCC, intel, arm, mips, riscv from qiling.const import QL_ARCH, QL_OS, QL_INTERCEPT from qiling.exception import QlErrorSyscallNotFound from qiling.os.os import QlOs @@ -52,6 +52,12 @@ def setReturnValue(self, value: int): self.ql.reg.v0 = value self.ql.reg.a3 = a3return +class riscv32(riscv.riscv): + pass + +class riscv64(riscv.riscv): + pass + class QlOsPosix(QlOs): def __init__(self, ql: Qiling): @@ -96,8 +102,8 @@ def __init__(self, ql: Qiling): QL_ARCH.MIPS : mipso32, QL_ARCH.X86 : intel32, QL_ARCH.X8664: intel64, - QL_ARCH.RISCV: intel.riscv, - QL_ARCH.RISCV64: intel.riscv, + QL_ARCH.RISCV: riscv32, + QL_ARCH.RISCV64: riscv64, }[self.ql.archtype](ql) self._fd = QlFileDes([0] * NR_OPEN) From 45dd725ff53fbe4265011835e83a704c3fd0233a Mon Sep 17 00:00:00 2001 From: dataisland Date: Tue, 9 Nov 2021 12:22:40 +0800 Subject: [PATCH 14/29] Update the riscv32 syscall table --- qiling/os/linux/map_syscall.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/qiling/os/linux/map_syscall.py b/qiling/os/linux/map_syscall.py index bedb292b8..6207636cf 100644 --- a/qiling/os/linux/map_syscall.py +++ b/qiling/os/linux/map_syscall.py @@ -1956,7 +1956,7 @@ def map_syscall(ql, syscall_num): 22: "epoll_pwait", 23: "dup", 24: "dup3", - 25: "fcntl64", + 25: "fcntl", 26: "inotify_init1", 27: "inotify_add_watch", 28: "inotify_rm_watch", @@ -1969,6 +1969,7 @@ def map_syscall(ql, syscall_num): 35: "unlinkat", 36: "symlinkat", 37: "linkat", + 38: "renameat", 39: "umount2", 40: "mount", 41: "pivot_root", @@ -1976,7 +1977,7 @@ def map_syscall(ql, syscall_num): 43: "statfs64", 44: "fstatfs64", 45: "truncate64", - 46: "ftruncate64", + 46: "ftruncate", 47: "fallocate", 48: "faccessat", 49: "chdir", @@ -1991,13 +1992,14 @@ def map_syscall(ql, syscall_num): 58: "vhangup", 59: "pipe2", 60: "quotactl", - 61: "getdents64", + 61: "getdents", + 62: "lseek", 63: "read", 64: "write", 65: "readv", 66: "writev", - 67: "pread64", - 68: "pwrite64", + 67: "pread", + 68: "pwrite", 69: "preadv", 70: "pwritev", 71: "sendfile64", @@ -2006,6 +2008,8 @@ def map_syscall(ql, syscall_num): 76: "splice", 77: "tee", 78: "readlinkat", + 79: "fstatat", + 80: "fstat", 81: "sync", 82: "fsync", 83: "fdatasync", @@ -2030,6 +2034,7 @@ def map_syscall(ql, syscall_num): 107: "timer_create", 109: "timer_getoverrun", 111: "timer_delete", + 113: "clock_gettime", 116: "syslog", 117: "ptrace", 118: "sched_setparam", @@ -2075,10 +2080,13 @@ def map_syscall(ql, syscall_num): 160: "uname", 161: "sethostname", 162: "setdomainname", + 163: "getrlimit", + 164: "setrlimit", 165: "getrusage", 166: "umask", 167: "prctl", 168: "getcpu", + 169: "gettimeofday", 172: "getpid", 173: "getppid", 174: "getuid", @@ -2126,7 +2134,7 @@ def map_syscall(ql, syscall_num): 219: "keyctl", 220: "clone", 221: "execve", - 222: "mmap2", + 222: "mmap", 223: "fadvise64_64", 224: "swapon", 225: "swapoff", @@ -2223,6 +2231,15 @@ def map_syscall(ql, syscall_num): 445: "landlock_add_rule", 446: "landlock_restrict_self", 448: "process_mrelease", + 1024: "open", + 1025: "link", + 1026: "unlink", + 1030: "mkdir", + 1033: "access", + 1038: "stat", + 1039: "lstat", + 1062: "time", + 2011: "getmainvars", } riscv64_syscall_table = { From b5804b726da16f07095628e229d8163e078333b5 Mon Sep 17 00:00:00 2001 From: dataisland Date: Tue, 9 Nov 2021 12:29:05 +0800 Subject: [PATCH 15/29] Try update the unicorn version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 5f768a315..9a11d028c 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ requirements = [ "capstone>=4.0.1", - "unicorn>=2.0.0-rc3", + "unicorn>=2.0.0-rc4", "pefile>=2021.9.3", "python-registry>=1.3.1", "keystone-engine>=0.9.2", From a181d00c3e782fa6ad4a439727d0f9fe927012c7 Mon Sep 17 00:00:00 2001 From: dataisland Date: Tue, 9 Nov 2021 12:31:46 +0800 Subject: [PATCH 16/29] Append riscv testcase --- examples/rootfs | 2 +- tests/test_posix.py | 1 + tests/test_riscv.py | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 tests/test_riscv.py diff --git a/examples/rootfs b/examples/rootfs index 9f5c6cbb9..9e2f4037f 160000 --- a/examples/rootfs +++ b/examples/rootfs @@ -1 +1 @@ -Subproject commit 9f5c6cbb9ccd6cc86effc1409adbbf164b6596c0 +Subproject commit 9e2f4037fe1129840a581b206e6c68d56f6d3edd diff --git a/tests/test_posix.py b/tests/test_posix.py index 07248e791..3f24483c6 100644 --- a/tests/test_posix.py +++ b/tests/test_posix.py @@ -9,6 +9,7 @@ from qiling import * from qiling.exception import * from test_elf import * +from test_riscv import * from test_qltool import * if __name__ == "__main__": diff --git a/tests/test_riscv.py b/tests/test_riscv.py new file mode 100644 index 000000000..45254ea9b --- /dev/null +++ b/tests/test_riscv.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# +# Cross Platform and Multi Architecture Advanced Binary Emulation Framework +# + +import sys, unittest +sys.path.append("..") + +from qiling.core import Qiling +from qiling.const import QL_VERBOSE +from qiling.extensions.pipe import SimpleOutStream + +class RISCVTest(unittest.TestCase): + def test_riscv32_hello_linux(self): + stdout = SimpleOutStream(1) + ql = Qiling(['../examples/rootfs/riscv32_linux/bin/hello'], '../examples/rootfs/riscv32_linux/', + verbose=QL_VERBOSE.DEBUG, stdout=stdout) + + + ql.run() + self.assertTrue(stdout.read() == b'Hello, World!\n') + + def test_riscv64_hello_linux(self): + stdout = SimpleOutStream(1) + ql = Qiling(['../examples/rootfs/riscv64_linux/bin/hello'], '../examples/rootfs/riscv64_linux/', + verbose=QL_VERBOSE.DEBUG, stdout=stdout) + + + ql.run() + self.assertTrue(stdout.read() == b'Hello, World!\n') + +if __name__ == "__main__": + unittest.main() \ No newline at end of file From 9b650c05d51e1d5b96a8fcfcab95f9c6e4870997 Mon Sep 17 00:00:00 2001 From: dataisland Date: Tue, 9 Nov 2021 12:51:50 +0800 Subject: [PATCH 17/29] Avoid close stdout during test --- tests/test_riscv.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/test_riscv.py b/tests/test_riscv.py index 45254ea9b..df90417ce 100644 --- a/tests/test_riscv.py +++ b/tests/test_riscv.py @@ -16,18 +16,21 @@ def test_riscv32_hello_linux(self): ql = Qiling(['../examples/rootfs/riscv32_linux/bin/hello'], '../examples/rootfs/riscv32_linux/', verbose=QL_VERBOSE.DEBUG, stdout=stdout) - - ql.run() + ql.run(end=0x66112) # avoid close 0, 1, 2 self.assertTrue(stdout.read() == b'Hello, World!\n') + del ql + def test_riscv64_hello_linux(self): stdout = SimpleOutStream(1) ql = Qiling(['../examples/rootfs/riscv64_linux/bin/hello'], '../examples/rootfs/riscv64_linux/', verbose=QL_VERBOSE.DEBUG, stdout=stdout) - ql.run() + ql.run(end=0x1249e) # avoid close 0, 1, 2 self.assertTrue(stdout.read() == b'Hello, World!\n') + del ql + if __name__ == "__main__": unittest.main() \ No newline at end of file From 3786178236a6edc4c13d79bef9d99f0b9d69d0dd Mon Sep 17 00:00:00 2001 From: dataisland Date: Tue, 9 Nov 2021 17:13:56 +0800 Subject: [PATCH 18/29] Fix riscv function hook --- qiling/os/linux/function_hook.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/qiling/os/linux/function_hook.py b/qiling/os/linux/function_hook.py index a030af8b3..f9bc6fb31 100644 --- a/qiling/os/linux/function_hook.py +++ b/qiling/os/linux/function_hook.py @@ -599,22 +599,20 @@ def __init__(self, ql, phoff, phnum, phentsize, load_base, hook_mem): self.add_function_hook = self.add_function_hook_relocation elif self.ql.archtype== QL_ARCH.RISCV: - # TODO: specific other parameters - # self.GLOB_DAT = 0 - # self.JMP_SLOT = 0 + self.GLOB_DAT = 21 + self.JMP_SLOT = 22 # ADDI x0, x0, 0 ins = b'\x00\x01' - # self.add_function_hook = self.add_function_hook_relocation + self.add_function_hook = self.add_function_hook_relocation elif self.ql.archtype== QL_ARCH.RISCV64: - # TODO: specific other parameters - # self.GLOB_DAT = 0 - # self.JMP_SLOT = 0 + self.GLOB_DAT = 21 + self.JMP_SLOT = 22 # ADDI x0, x0, 0 ins = b'\x00\x01' - # self.add_function_hook = self.add_function_hook_relocation + self.add_function_hook = self.add_function_hook_relocation self._parse() if self.rel != None: From 045f97cf25739e8fd47a86fc88525704deff5ab9 Mon Sep 17 00:00:00 2001 From: dataisland Date: Tue, 9 Nov 2021 17:14:22 +0800 Subject: [PATCH 19/29] Add riscv linux open flags --- qiling/os/posix/const.py | 18 ++++++++++++++++++ qiling/os/posix/const_mapping.py | 3 +++ 2 files changed, 21 insertions(+) diff --git a/qiling/os/posix/const.py b/qiling/os/posix/const.py index 67da6d924..d1d622a82 100644 --- a/qiling/os/posix/const.py +++ b/qiling/os/posix/const.py @@ -493,6 +493,24 @@ 'O_LARGEFILE': 0x2000 } +linux_riscv_open_flags = { + 'O_RDONLY': 0x0, + 'O_WRONLY': 0x1, + 'O_RDWR': 0x2, + 'O_NONBLOCK': 0x800, + 'O_APPEND': 0x400, + 'O_ASYNC': 0x2000, + 'O_SYNC': 0x101000, + 'O_NOFOLLOW': 0x20000, + 'O_CREAT': 0x40, + 'O_TRUNC': 0x200, + 'O_EXCL': 0x80, + 'O_NOCTTY': 0x100, + 'O_DIRECTORY': 0x10000, + 'O_BINARY' : None, + 'O_LARGEFILE': None, +} + freebsd_x86_open_flags = { 'O_RDONLY': 0x0, 'O_WRONLY': 0x1, diff --git a/qiling/os/posix/const_mapping.py b/qiling/os/posix/const_mapping.py index 3334f5651..c314bb387 100644 --- a/qiling/os/posix/const_mapping.py +++ b/qiling/os/posix/const_mapping.py @@ -56,6 +56,9 @@ def flag_mapping(flags, mapping_name, mapping_from, mapping_to): f = linux_arm_open_flags elif ql.archtype == QL_ARCH.MIPS: f = linux_mips_open_flags + elif ql.archtype in (QL_ARCH.RISCV, QL_ARCH.RISCV64): + f = linux_riscv_open_flags + elif ql.ostype == QL_OS.MACOS: if ql.archtype in (QL_ARCH.X86, QL_ARCH.X8664): f = macos_x86_open_flags From 937a594fe1d06a38984ecd759660b696b8535138 Mon Sep 17 00:00:00 2001 From: dataisland Date: Tue, 9 Nov 2021 17:25:00 +0800 Subject: [PATCH 20/29] Refactor the mman --- qiling/os/posix/syscall/mman.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/qiling/os/posix/syscall/mman.py b/qiling/os/posix/syscall/mman.py index 6993376e7..83ca65725 100755 --- a/qiling/os/posix/syscall/mman.py +++ b/qiling/os/posix/syscall/mman.py @@ -63,20 +63,18 @@ def syscall_mmap_impl(ql: Qiling, addr: int, mlen: int, prot: int, flags: int, f 2 : 'mmap2' }[ver] - # ql.log.debug(f'{api_name}({addr:#x}, {mlen:#x}, {mmap_prot_mapping(prot)} ({prot:#x}), {mmap_flag_mapping(flags)} ({flags:#x}), {fd:d}, {pgoffset:#x})') - - # FIXME - # this is ugly patch, we might need to get value from elf parse, - # is32bit or is64bit value not by arch - if (ql.archtype == QL_ARCH.ARM64) or (ql.archtype == QL_ARCH.X8664): + if ql.archbit == 64: fd = ql.unpack64(ql.pack64(fd)) - elif (ql.archtype == QL_ARCH.MIPS): + + elif ql.archtype == QL_ARCH.MIPS: MAP_ANONYMOUS = 2048 if ver == 2: pgoffset = pgoffset * 4096 - elif (ql.archtype== QL_ARCH.ARM) and (ql.ostype== QL_OS.QNX): - MAP_ANONYMOUS=0x00080000 + + elif ql.archtype == QL_ARCH.ARM and ql.ostype== QL_OS.QNX: + MAP_ANONYMOUS = 0x00080000 fd = ql.unpack32s(ql.pack32s(fd)) + else: fd = ql.unpack32s(ql.pack32(fd)) if ver == 2: @@ -85,6 +83,7 @@ def syscall_mmap_impl(ql: Qiling, addr: int, mlen: int, prot: int, flags: int, f mmap_base = addr need_mmap = True eff_mmap_size = ((mlen + 0x1000 - 1) // 0x1000) * 0x1000 + # align eff_mmap_size to page boundary aligned_address = (addr >> 12) << 12 eff_mmap_size -= mmap_base - aligned_address From f524ab1c857954223cf54b9cbb8d5c9554f6f385 Mon Sep 17 00:00:00 2001 From: dataisland Date: Tue, 9 Nov 2021 17:42:23 +0800 Subject: [PATCH 21/29] Warning is ok when intrrupt --- qiling/core_hooks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiling/core_hooks.py b/qiling/core_hooks.py index 1b70e817d..832bdafac 100644 --- a/qiling/core_hooks.py +++ b/qiling/core_hooks.py @@ -54,7 +54,7 @@ def _hook_intr_cb(self, uc: Uc, intno: int, pack_data) -> None: break if not handled: - raise QlErrorCoreHook("_hook_intr_cb : not handled") + ql.log.warning("[+] Unhandled Interupt: %i" % (intno)) def _hook_insn_cb(self, uc: Uc, *args): From baa86ab6a4d1a954671290acdd22fd8caa7d3979 Mon Sep 17 00:00:00 2001 From: dataisland Date: Tue, 9 Nov 2021 17:42:46 +0800 Subject: [PATCH 22/29] Fix some typo --- qiling/os/linux/linux.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/qiling/os/linux/linux.py b/qiling/os/linux/linux.py index bac4aba58..60a49fc81 100644 --- a/qiling/os/linux/linux.py +++ b/qiling/os/linux/linux.py @@ -96,11 +96,10 @@ def load(self): self.thread_class = None for i in range(NR_OPEN): - if hasattr(self.fd[i], 'close_on_exec') and \ - self.fd[i].close_on_exec: + if getattr(self.fd[i], 'close_on_exec', 0): self.fd[i] = 0 - def hook_syscall(self, int= None, intno= None): + def hook_syscall(self, ql, intno = None): return self.load_syscall() From 208edddacf3a537e7fc0c53ed179b2c3d5203126 Mon Sep 17 00:00:00 2001 From: dataisland Date: Tue, 9 Nov 2021 17:43:23 +0800 Subject: [PATCH 23/29] Add riscv dyn testcase --- examples/rootfs | 2 +- tests/test_riscv.py | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/examples/rootfs b/examples/rootfs index 9e2f4037f..7a7c69efb 160000 --- a/examples/rootfs +++ b/examples/rootfs @@ -1 +1 @@ -Subproject commit 9e2f4037fe1129840a581b206e6c68d56f6d3edd +Subproject commit 7a7c69efb060ad746969eaf9ec67741de1b3aec6 diff --git a/tests/test_riscv.py b/tests/test_riscv.py index df90417ce..3572c2fbe 100644 --- a/tests/test_riscv.py +++ b/tests/test_riscv.py @@ -32,5 +32,16 @@ def test_riscv64_hello_linux(self): del ql + def test_riscv64_hello_dyn_linux(self): + stdout = SimpleOutStream(1) + ql = Qiling(['../examples/rootfs/riscv64_linux/bin/hello-linux'], '../examples/rootfs/riscv64_linux/', + verbose=QL_VERBOSE.DEBUG, stdout=stdout) + + + ql.run(end=0x1249e) # avoid close 0, 1, 2 + self.assertTrue(stdout.read() == b'Hello, World!\n') + + del ql + if __name__ == "__main__": unittest.main() \ No newline at end of file From c67c5388ad2d53aa7dff0bb08975c030ad361df4 Mon Sep 17 00:00:00 2001 From: dataisland Date: Tue, 9 Nov 2021 18:03:36 +0800 Subject: [PATCH 24/29] Add LinuxRISCVStat --- qiling/os/posix/syscall/stat.py | 54 +++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/qiling/os/posix/syscall/stat.py b/qiling/os/posix/syscall/stat.py index 10b9f9fa1..b3a251090 100644 --- a/qiling/os/posix/syscall/stat.py +++ b/qiling/os/posix/syscall/stat.py @@ -717,6 +717,56 @@ class LinuxARM64EBStat(ctypes.BigEndianStructure): _pack_ = 8 +# Srouce: https://github.com/riscv-collab/riscv-gnu-toolchain/blob/master/linux-headers/include/asm-generic/stat.h +# struct stat { +# unsigned long st_dev; /* Device. */ +# unsigned long st_ino; /* File serial number. */ +# unsigned int st_mode; /* File mode. */ +# unsigned int st_nlink; /* Link count. */ +# unsigned int st_uid; /* User ID of the file's owner. */ +# unsigned int st_gid; /* Group ID of the file's group. */ +# unsigned long st_rdev; /* Device number, if device. */ +# unsigned long __pad1; +# long st_size; /* Size of file, in bytes. */ +# int st_blksize; /* Optimal block size for I/O. */ +# int __pad2; +# long st_blocks; /* Number 512-byte blocks allocated. */ +# long st_atime; /* Time of last access. */ +# unsigned long st_atime_nsec; +# long st_mtime; /* Time of last modification. */ +# unsigned long st_mtime_nsec; +# long st_ctime; /* Time of last status change. */ +# unsigned long st_ctime_nsec; +# unsigned int __unused4; +# unsigned int __unused5; +# }; + +class LinuxRISCVStat(ctypes.Structure): + _fields_ = [ + ("st_dev", ctypes.c_uint64), + ("st_ino", ctypes.c_uint64), + ("st_mode", ctypes.c_uint32), + ("st_nlink", ctypes.c_uint32), + ("st_uid", ctypes.c_uint32), + ("st_gid", ctypes.c_uint32), + ("st_rdev", ctypes.c_uint64), + ("__pad1", ctypes.c_uint64), + ("st_size", ctypes.c_int64), + ("st_blksize", ctypes.c_int32), + ("__pad2", ctypes.c_int32), + ("st_blocks", ctypes.c_int64), + ("st_atime", ctypes.c_int64), + ("st_atime_nsec", ctypes.c_uint64), + ("st_mtime", ctypes.c_int64), + ("st_mtime_nsec", ctypes.c_uint64), + ("st_ctime", ctypes.c_int64), + ("st_ctime_nsec", ctypes.c_uint64), + ("__unused4", ctypes.c_uint32), + ("__unused5", ctypes.c_uint32), + ] + + _pack_ = 8 + # Source: openqnx lib/c/public/sys/stat.h # # struct stat { @@ -887,6 +937,8 @@ def get_stat64_struct(ql: Qiling): return LinuxMips32Stat64() elif ql.archtype in (QL_ARCH.ARM, QL_ARCH.ARM_THUMB): return LinuxARMStat64() + elif ql.archtype in (QL_ARCH.RISCV, QL_ARCH.RISCV64): + return LinuxRISCVStat() elif ql.ostype == QL_OS.MACOS: return MacOSStat64() elif ql.ostype == QL_OS.QNX: @@ -922,6 +974,8 @@ def get_stat_struct(ql: Qiling): return LinuxARM64Stat() else: return LinuxARM64EBStat() + elif ql.archtype in (QL_ARCH.RISCV, QL_ARCH.RISCV64): + return LinuxRISCVStat() elif ql.ostype == QL_OS.QNX: if ql.archtype == QL_ARCH.ARM64: return QNXARM64Stat() From 6e2213ef007aa5f31b717544fff11eacc5f823fc Mon Sep 17 00:00:00 2001 From: dataisland Date: Tue, 9 Nov 2021 21:22:06 +0800 Subject: [PATCH 25/29] Refactor the output of syscall --- qiling/os/posix/posix.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qiling/os/posix/posix.py b/qiling/os/posix/posix.py index d5787cbab..437036145 100644 --- a/qiling/os/posix/posix.py +++ b/qiling/os/posix/posix.py @@ -243,7 +243,8 @@ def load_syscall(self): raise e # print out log entry - syscall_basename = syscall_name[len(SYSCALL_PREF):] + syscall_basename = syscall_name[len(SYSCALL_PREF) if syscall_name.startswith(SYSCALL_PREF) else 0:] + args = [] for name, value in zip(param_names, params): @@ -253,7 +254,7 @@ def load_syscall(self): args.append((name, f'{value:#x}')) - sret = retval and QlOsPosix.getNameFromErrorCode(retval) + sret = QlOsPosix.getNameFromErrorCode(retval) self.utils.print_function(self.ql.reg.arch_pc, syscall_basename, args, sret, False) # record syscall statistics From 0ec3783e57fc0ad1108f03eb816b50a026fb43e3 Mon Sep 17 00:00:00 2001 From: dataisland Date: Tue, 9 Nov 2021 21:22:22 +0800 Subject: [PATCH 26/29] Fix the riscv test --- tests/test_riscv.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tests/test_riscv.py b/tests/test_riscv.py index 3572c2fbe..012a47bbe 100644 --- a/tests/test_riscv.py +++ b/tests/test_riscv.py @@ -7,16 +7,19 @@ sys.path.append("..") from qiling.core import Qiling -from qiling.const import QL_VERBOSE +from qiling.const import QL_VERBOSE, QL_INTERCEPT from qiling.extensions.pipe import SimpleOutStream class RISCVTest(unittest.TestCase): def test_riscv32_hello_linux(self): stdout = SimpleOutStream(1) ql = Qiling(['../examples/rootfs/riscv32_linux/bin/hello'], '../examples/rootfs/riscv32_linux/', - verbose=QL_VERBOSE.DEBUG, stdout=stdout) - - ql.run(end=0x66112) # avoid close 0, 1, 2 + verbose=QL_VERBOSE.DEFAULT, stdout=stdout) + + def close(ql, fd): + return 0 + ql.set_syscall("close", close, QL_INTERCEPT.CALL) + ql.run() self.assertTrue(stdout.read() == b'Hello, World!\n') del ql @@ -24,10 +27,12 @@ def test_riscv32_hello_linux(self): def test_riscv64_hello_linux(self): stdout = SimpleOutStream(1) ql = Qiling(['../examples/rootfs/riscv64_linux/bin/hello'], '../examples/rootfs/riscv64_linux/', - verbose=QL_VERBOSE.DEBUG, stdout=stdout) - + verbose=QL_VERBOSE.DEFAULT, stdout=stdout) - ql.run(end=0x1249e) # avoid close 0, 1, 2 + def close(ql, fd): + return 0 + ql.set_syscall("close", close, QL_INTERCEPT.CALL) + ql.run() self.assertTrue(stdout.read() == b'Hello, World!\n') del ql @@ -35,10 +40,9 @@ def test_riscv64_hello_linux(self): def test_riscv64_hello_dyn_linux(self): stdout = SimpleOutStream(1) ql = Qiling(['../examples/rootfs/riscv64_linux/bin/hello-linux'], '../examples/rootfs/riscv64_linux/', - verbose=QL_VERBOSE.DEBUG, stdout=stdout) - + verbose=QL_VERBOSE.DEFAULT, stdout=stdout) - ql.run(end=0x1249e) # avoid close 0, 1, 2 + ql.run() self.assertTrue(stdout.read() == b'Hello, World!\n') del ql From ec3494899d2651984797de5733696ef79697bc69 Mon Sep 17 00:00:00 2001 From: dataisland Date: Tue, 9 Nov 2021 23:24:53 +0800 Subject: [PATCH 27/29] Update the register map to rc4 --- qiling/arch/riscv_const.py | 336 ++++++++++++++++++++++++++++++------- 1 file changed, 271 insertions(+), 65 deletions(-) diff --git a/qiling/arch/riscv_const.py b/qiling/arch/riscv_const.py index eb05813b2..d85b68f76 100644 --- a/qiling/arch/riscv_const.py +++ b/qiling/arch/riscv_const.py @@ -4,72 +4,278 @@ # from unicorn.riscv_const import * +from enum import IntEnum + + +reg_general_map = { + "x0": UC_RISCV_REG_X0, + "x1": UC_RISCV_REG_X1, + "x2": UC_RISCV_REG_X2, + "x3": UC_RISCV_REG_X3, + "x4": UC_RISCV_REG_X4, + "x5": UC_RISCV_REG_X5, + "x6": UC_RISCV_REG_X6, + "x7": UC_RISCV_REG_X7, + "x8": UC_RISCV_REG_X8, + "x9": UC_RISCV_REG_X9, + "x10": UC_RISCV_REG_X10, + "x11": UC_RISCV_REG_X11, + "x12": UC_RISCV_REG_X12, + "x13": UC_RISCV_REG_X13, + "x14": UC_RISCV_REG_X14, + "x15": UC_RISCV_REG_X15, + "x16": UC_RISCV_REG_X16, + "x17": UC_RISCV_REG_X17, + "x18": UC_RISCV_REG_X18, + "x19": UC_RISCV_REG_X19, + "x20": UC_RISCV_REG_X20, + "x21": UC_RISCV_REG_X21, + "x22": UC_RISCV_REG_X22, + "x23": UC_RISCV_REG_X23, + "x24": UC_RISCV_REG_X24, + "x25": UC_RISCV_REG_X25, + "x26": UC_RISCV_REG_X26, + "x27": UC_RISCV_REG_X27, + "x28": UC_RISCV_REG_X28, + "x29": UC_RISCV_REG_X29, + "x30": UC_RISCV_REG_X30, + "x31": UC_RISCV_REG_X31, +} + +reg_csr_map = { + "ustatus": UC_RISCV_REG_USTATUS, + "uie": UC_RISCV_REG_UIE, + "utvec": UC_RISCV_REG_UTVEC, + "uscratch": UC_RISCV_REG_USCRATCH, + "uepc": UC_RISCV_REG_UEPC, + "ucause": UC_RISCV_REG_UCAUSE, + "utval": UC_RISCV_REG_UTVAL, + "uip": UC_RISCV_REG_UIP, + "fflags": UC_RISCV_REG_FFLAGS, + "frm": UC_RISCV_REG_FRM, + "fcsr": UC_RISCV_REG_FCSR, + "cycle": UC_RISCV_REG_CYCLE, + "time": UC_RISCV_REG_TIME, + "instret": UC_RISCV_REG_INSTRET, + "hpmcounter3": UC_RISCV_REG_HPMCOUNTER3, + "hpmcounter4": UC_RISCV_REG_HPMCOUNTER4, + "hpmcounter5": UC_RISCV_REG_HPMCOUNTER5, + "hpmcounter6": UC_RISCV_REG_HPMCOUNTER6, + "hpmcounter7": UC_RISCV_REG_HPMCOUNTER7, + "hpmcounter8": UC_RISCV_REG_HPMCOUNTER8, + "hpmcounter9": UC_RISCV_REG_HPMCOUNTER9, + "hpmcounter10": UC_RISCV_REG_HPMCOUNTER10, + "hpmcounter11": UC_RISCV_REG_HPMCOUNTER11, + "hpmcounter12": UC_RISCV_REG_HPMCOUNTER12, + "hpmcounter13": UC_RISCV_REG_HPMCOUNTER13, + "hpmcounter14": UC_RISCV_REG_HPMCOUNTER14, + "hpmcounter15": UC_RISCV_REG_HPMCOUNTER15, + "hpmcounter16": UC_RISCV_REG_HPMCOUNTER16, + "hpmcounter17": UC_RISCV_REG_HPMCOUNTER17, + "hpmcounter18": UC_RISCV_REG_HPMCOUNTER18, + "hpmcounter19": UC_RISCV_REG_HPMCOUNTER19, + "hpmcounter20": UC_RISCV_REG_HPMCOUNTER20, + "hpmcounter21": UC_RISCV_REG_HPMCOUNTER21, + "hpmcounter22": UC_RISCV_REG_HPMCOUNTER22, + "hpmcounter23": UC_RISCV_REG_HPMCOUNTER23, + "hpmcounter24": UC_RISCV_REG_HPMCOUNTER24, + "hpmcounter25": UC_RISCV_REG_HPMCOUNTER25, + "hpmcounter26": UC_RISCV_REG_HPMCOUNTER26, + "hpmcounter27": UC_RISCV_REG_HPMCOUNTER27, + "hpmcounter28": UC_RISCV_REG_HPMCOUNTER28, + "hpmcounter29": UC_RISCV_REG_HPMCOUNTER29, + "hpmcounter30": UC_RISCV_REG_HPMCOUNTER30, + "hpmcounter31": UC_RISCV_REG_HPMCOUNTER31, + "cycleh": UC_RISCV_REG_CYCLEH, + "timeh": UC_RISCV_REG_TIMEH, + "instreth": UC_RISCV_REG_INSTRETH, + "hpmcounter3h": UC_RISCV_REG_HPMCOUNTER3H, + "hpmcounter4h": UC_RISCV_REG_HPMCOUNTER4H, + "hpmcounter5h": UC_RISCV_REG_HPMCOUNTER5H, + "hpmcounter6h": UC_RISCV_REG_HPMCOUNTER6H, + "hpmcounter7h": UC_RISCV_REG_HPMCOUNTER7H, + "hpmcounter8h": UC_RISCV_REG_HPMCOUNTER8H, + "hpmcounter9h": UC_RISCV_REG_HPMCOUNTER9H, + "hpmcounter10h": UC_RISCV_REG_HPMCOUNTER10H, + "hpmcounter11h": UC_RISCV_REG_HPMCOUNTER11H, + "hpmcounter12h": UC_RISCV_REG_HPMCOUNTER12H, + "hpmcounter13h": UC_RISCV_REG_HPMCOUNTER13H, + "hpmcounter14h": UC_RISCV_REG_HPMCOUNTER14H, + "hpmcounter15h": UC_RISCV_REG_HPMCOUNTER15H, + "hpmcounter16h": UC_RISCV_REG_HPMCOUNTER16H, + "hpmcounter17h": UC_RISCV_REG_HPMCOUNTER17H, + "hpmcounter18h": UC_RISCV_REG_HPMCOUNTER18H, + "hpmcounter19h": UC_RISCV_REG_HPMCOUNTER19H, + "hpmcounter20h": UC_RISCV_REG_HPMCOUNTER20H, + "hpmcounter21h": UC_RISCV_REG_HPMCOUNTER21H, + "hpmcounter22h": UC_RISCV_REG_HPMCOUNTER22H, + "hpmcounter23h": UC_RISCV_REG_HPMCOUNTER23H, + "hpmcounter24h": UC_RISCV_REG_HPMCOUNTER24H, + "hpmcounter25h": UC_RISCV_REG_HPMCOUNTER25H, + "hpmcounter26h": UC_RISCV_REG_HPMCOUNTER26H, + "hpmcounter27h": UC_RISCV_REG_HPMCOUNTER27H, + "hpmcounter28h": UC_RISCV_REG_HPMCOUNTER28H, + "hpmcounter29h": UC_RISCV_REG_HPMCOUNTER29H, + "hpmcounter30h": UC_RISCV_REG_HPMCOUNTER30H, + "hpmcounter31h": UC_RISCV_REG_HPMCOUNTER31H, + "mcycle": UC_RISCV_REG_MCYCLE, + "minstret": UC_RISCV_REG_MINSTRET, + "mcycleh": UC_RISCV_REG_MCYCLEH, + "minstreth": UC_RISCV_REG_MINSTRETH, + "mvendorid": UC_RISCV_REG_MVENDORID, + "marchid": UC_RISCV_REG_MARCHID, + "mimpid": UC_RISCV_REG_MIMPID, + "mhartid": UC_RISCV_REG_MHARTID, + "mstatus": UC_RISCV_REG_MSTATUS, + "misa": UC_RISCV_REG_MISA, + "medeleg": UC_RISCV_REG_MEDELEG, + "mideleg": UC_RISCV_REG_MIDELEG, + "mie": UC_RISCV_REG_MIE, + "mtvec": UC_RISCV_REG_MTVEC, + "mcounteren": UC_RISCV_REG_MCOUNTEREN, + "mstatush": UC_RISCV_REG_MSTATUSH, + "mucounteren": UC_RISCV_REG_MUCOUNTEREN, + "mscounteren": UC_RISCV_REG_MSCOUNTEREN, + "mhcounteren": UC_RISCV_REG_MHCOUNTEREN, + "mscratch": UC_RISCV_REG_MSCRATCH, + "mepc": UC_RISCV_REG_MEPC, + "mcause": UC_RISCV_REG_MCAUSE, + "mtval": UC_RISCV_REG_MTVAL, + "mip": UC_RISCV_REG_MIP, + "mbadaddr": UC_RISCV_REG_MBADADDR, + "sstatus": UC_RISCV_REG_SSTATUS, + "sedeleg": UC_RISCV_REG_SEDELEG, + "sideleg": UC_RISCV_REG_SIDELEG, + "sie": UC_RISCV_REG_SIE, + "stvec": UC_RISCV_REG_STVEC, + "scounteren": UC_RISCV_REG_SCOUNTEREN, + "sscratch": UC_RISCV_REG_SSCRATCH, + "sepc": UC_RISCV_REG_SEPC, + "scause": UC_RISCV_REG_SCAUSE, + "stval": UC_RISCV_REG_STVAL, + "sip": UC_RISCV_REG_SIP, + "sbadaddr": UC_RISCV_REG_SBADADDR, + "sptbr": UC_RISCV_REG_SPTBR, + "satp": UC_RISCV_REG_SATP, + "hstatus": UC_RISCV_REG_HSTATUS, + "hedeleg": UC_RISCV_REG_HEDELEG, + "hideleg": UC_RISCV_REG_HIDELEG, + "hie": UC_RISCV_REG_HIE, + "hcounteren": UC_RISCV_REG_HCOUNTEREN, + "htval": UC_RISCV_REG_HTVAL, + "hip": UC_RISCV_REG_HIP, + "htinst": UC_RISCV_REG_HTINST, + "hgatp": UC_RISCV_REG_HGATP, + "htimedelta": UC_RISCV_REG_HTIMEDELTA, + "htimedeltah": UC_RISCV_REG_HTIMEDELTAH, +} + +reg_float_map = { + "f0": UC_RISCV_REG_F0, + "f1": UC_RISCV_REG_F1, + "f2": UC_RISCV_REG_F2, + "f3": UC_RISCV_REG_F3, + "f4": UC_RISCV_REG_F4, + "f5": UC_RISCV_REG_F5, + "f6": UC_RISCV_REG_F6, + "f7": UC_RISCV_REG_F7, + "f8": UC_RISCV_REG_F8, + "f9": UC_RISCV_REG_F9, + "f10": UC_RISCV_REG_F10, + "f11": UC_RISCV_REG_F11, + "f12": UC_RISCV_REG_F12, + "f13": UC_RISCV_REG_F13, + "f14": UC_RISCV_REG_F14, + "f15": UC_RISCV_REG_F15, + "f16": UC_RISCV_REG_F16, + "f17": UC_RISCV_REG_F17, + "f18": UC_RISCV_REG_F18, + "f19": UC_RISCV_REG_F19, + "f20": UC_RISCV_REG_F20, + "f21": UC_RISCV_REG_F21, + "f22": UC_RISCV_REG_F22, + "f23": UC_RISCV_REG_F23, + "f24": UC_RISCV_REG_F24, + "f25": UC_RISCV_REG_F25, + "f26": UC_RISCV_REG_F26, + "f27": UC_RISCV_REG_F27, + "f28": UC_RISCV_REG_F28, + "f29": UC_RISCV_REG_F29, + "f30": UC_RISCV_REG_F30, + "f31": UC_RISCV_REG_F31, +} reg_map = { - "zero": UC_RISCV_REG_ZERO, - "ra": UC_RISCV_REG_RA, - "sp": UC_RISCV_REG_SP, - "gp": UC_RISCV_REG_GP, - "tp": UC_RISCV_REG_TP, - "t0": UC_RISCV_REG_T0, - "t1": UC_RISCV_REG_T1, - "t2": UC_RISCV_REG_T2, - "s0": UC_RISCV_REG_S0, - "fp": UC_RISCV_REG_FP, - "s1": UC_RISCV_REG_S1, - "a0": UC_RISCV_REG_A0, - "a1": UC_RISCV_REG_A1, - "a2": UC_RISCV_REG_A2, - "a3": UC_RISCV_REG_A3, - "a4": UC_RISCV_REG_A4, - "a5": UC_RISCV_REG_A5, - "a6": UC_RISCV_REG_A6, - "a7": UC_RISCV_REG_A7, - "s2": UC_RISCV_REG_S2, - "s3": UC_RISCV_REG_S3, - "s4": UC_RISCV_REG_S4, - "s5": UC_RISCV_REG_S5, - "s6": UC_RISCV_REG_S6, - "s7": UC_RISCV_REG_S7, - "s8": UC_RISCV_REG_S8, - "s9": UC_RISCV_REG_S9, - "s10": UC_RISCV_REG_S10, - "s11": UC_RISCV_REG_S11, - "t3": UC_RISCV_REG_T3, - "t4": UC_RISCV_REG_T4, - "t5": UC_RISCV_REG_T5, - "t6": UC_RISCV_REG_T6, - "ft0": UC_RISCV_REG_FT0, - "ft1": UC_RISCV_REG_FT1, - "ft2": UC_RISCV_REG_FT2, - "ft3": UC_RISCV_REG_FT3, - "ft4": UC_RISCV_REG_FT4, - "ft5": UC_RISCV_REG_FT5, - "ft6": UC_RISCV_REG_FT6, - "ft7": UC_RISCV_REG_FT7, - "fs0": UC_RISCV_REG_FS0, - "fs1": UC_RISCV_REG_FS1, - "fa0": UC_RISCV_REG_FA0, - "fa1": UC_RISCV_REG_FA1, - "fa2": UC_RISCV_REG_FA2, - "fa3": UC_RISCV_REG_FA3, - "fa4": UC_RISCV_REG_FA4, - "fa5": UC_RISCV_REG_FA5, - "fa6": UC_RISCV_REG_FA6, - "fa7": UC_RISCV_REG_FA7, - "fs2": UC_RISCV_REG_FS2, - "fs3": UC_RISCV_REG_FS3, - "fs4": UC_RISCV_REG_FS4, - "fs5": UC_RISCV_REG_FS5, - "fs6": UC_RISCV_REG_FS6, - "fs7": UC_RISCV_REG_FS7, - "fs8": UC_RISCV_REG_FS8, - "fs9": UC_RISCV_REG_FS9, - "fs10": UC_RISCV_REG_FS10, - "fs11": UC_RISCV_REG_FS11, - "ft8": UC_RISCV_REG_FT8, - "ft9": UC_RISCV_REG_FT9, - "ft10": UC_RISCV_REG_FT10, - "ft11": UC_RISCV_REG_FT11, "pc": UC_RISCV_REG_PC, + "zero": UC_RISCV_REG_ZERO, + "ra": UC_RISCV_REG_RA, + "sp": UC_RISCV_REG_SP, + "gp": UC_RISCV_REG_GP, + "tp": UC_RISCV_REG_TP, + "t0": UC_RISCV_REG_T0, + "t1": UC_RISCV_REG_T1, + "t2": UC_RISCV_REG_T2, + "s0": UC_RISCV_REG_S0, + "fp": UC_RISCV_REG_FP, + "s1": UC_RISCV_REG_S1, + "a0": UC_RISCV_REG_A0, + "a1": UC_RISCV_REG_A1, + "a2": UC_RISCV_REG_A2, + "a3": UC_RISCV_REG_A3, + "a4": UC_RISCV_REG_A4, + "a5": UC_RISCV_REG_A5, + "a6": UC_RISCV_REG_A6, + "a7": UC_RISCV_REG_A7, + "s2": UC_RISCV_REG_S2, + "s3": UC_RISCV_REG_S3, + "s4": UC_RISCV_REG_S4, + "s5": UC_RISCV_REG_S5, + "s6": UC_RISCV_REG_S6, + "s7": UC_RISCV_REG_S7, + "s8": UC_RISCV_REG_S8, + "s9": UC_RISCV_REG_S9, + "s10": UC_RISCV_REG_S10, + "s11": UC_RISCV_REG_S11, + "t3": UC_RISCV_REG_T3, + "t4": UC_RISCV_REG_T4, + "t5": UC_RISCV_REG_T5, + "t6": UC_RISCV_REG_T6, + "ft0": UC_RISCV_REG_FT0, + "ft1": UC_RISCV_REG_FT1, + "ft2": UC_RISCV_REG_FT2, + "ft3": UC_RISCV_REG_FT3, + "ft4": UC_RISCV_REG_FT4, + "ft5": UC_RISCV_REG_FT5, + "ft6": UC_RISCV_REG_FT6, + "ft7": UC_RISCV_REG_FT7, + "fs0": UC_RISCV_REG_FS0, + "fs1": UC_RISCV_REG_FS1, + "fa0": UC_RISCV_REG_FA0, + "fa1": UC_RISCV_REG_FA1, + "fa2": UC_RISCV_REG_FA2, + "fa3": UC_RISCV_REG_FA3, + "fa4": UC_RISCV_REG_FA4, + "fa5": UC_RISCV_REG_FA5, + "fa6": UC_RISCV_REG_FA6, + "fa7": UC_RISCV_REG_FA7, + "fs2": UC_RISCV_REG_FS2, + "fs3": UC_RISCV_REG_FS3, + "fs4": UC_RISCV_REG_FS4, + "fs5": UC_RISCV_REG_FS5, + "fs6": UC_RISCV_REG_FS6, + "fs7": UC_RISCV_REG_FS7, + "fs8": UC_RISCV_REG_FS8, + "fs9": UC_RISCV_REG_FS9, + "fs10": UC_RISCV_REG_FS10, + "fs11": UC_RISCV_REG_FS11, + "ft8": UC_RISCV_REG_FT8, + "ft9": UC_RISCV_REG_FT9, + "ft10": UC_RISCV_REG_FT10, + "ft11": UC_RISCV_REG_FT11, } + +class MSTATUS(IntEnum): + FS_OFF = 0 + FS_INITIAL = 1 << 13 + FS_CLEAN = 2 << 13 + FS_DIRTY = 3 << 13 From cbcbf9cd4e69a7118c702cbdc6c2f3e2fb44eef8 Mon Sep 17 00:00:00 2001 From: dataisland Date: Tue, 9 Nov 2021 23:25:07 +0800 Subject: [PATCH 28/29] Add defualt float support --- qiling/arch/riscv.py | 12 +++++++++++- qiling/arch/riscv64.py | 9 +++------ qiling/os/linux/linux.py | 2 ++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/qiling/arch/riscv.py b/qiling/arch/riscv.py index ab0b29ec7..64fc5aff8 100644 --- a/qiling/arch/riscv.py +++ b/qiling/arch/riscv.py @@ -17,7 +17,14 @@ class QlArchRISCV(QlArch): def __init__(self, ql: Qiling): super().__init__(ql) - self.ql.reg.expand_mapping(reg_map) + reg_maps = ( + reg_map, + reg_csr_map, + reg_float_map, + ) + + for reg_maper in reg_maps: + self.ql.reg.expand_mapping(reg_maper) self.ql.reg.register_sp(reg_map["sp"]) self.ql.reg.register_pc(reg_map["pc"]) @@ -34,3 +41,6 @@ def create_disassembler(self) -> Cs: def create_assembler(self) -> Ks: raise QlErrorNotImplemented("Keystone does not yet support riscv") + + def enable_float(self): + self.ql.reg.mstatus = self.ql.reg.mstatus | MSTATUS.FS_DIRTY diff --git a/qiling/arch/riscv64.py b/qiling/arch/riscv64.py index 51254d87f..c7a31d081 100644 --- a/qiling/arch/riscv64.py +++ b/qiling/arch/riscv64.py @@ -8,19 +8,16 @@ from keystone import Ks from qiling import Qiling -from qiling.arch.arch import QlArch from qiling.arch.riscv_const import * from qiling.exception import QlErrorNotImplemented +from .riscv import QlArchRISCV -class QlArchRISCV64(QlArch): + +class QlArchRISCV64(QlArchRISCV): def __init__(self, ql: Qiling): super().__init__(ql) - self.ql.reg.expand_mapping(reg_map) - self.ql.reg.register_sp(reg_map["sp"]) - self.ql.reg.register_pc(reg_map["pc"]) - # get initialized unicorn engine def get_init_uc(self) -> Uc: return Uc(UC_ARCH_RISCV, UC_MODE_RISCV64) diff --git a/qiling/os/linux/linux.py b/qiling/os/linux/linux.py index 60a49fc81..2a21016f1 100644 --- a/qiling/os/linux/linux.py +++ b/qiling/os/linux/linux.py @@ -88,10 +88,12 @@ def load(self): self.thread_class = thread.QlLinuxX8664Thread elif self.ql.archtype == QL_ARCH.RISCV: + self.ql.arch.enable_float() self.ql.hook_intno(self.hook_syscall, 8) self.thread_class = None elif self.ql.archtype == QL_ARCH.RISCV64: + self.ql.arch.enable_float() self.ql.hook_intno(self.hook_syscall, 8) self.thread_class = None From 025cfc304e9ca0b9004a166717c33bf8c57d154f Mon Sep 17 00:00:00 2001 From: dataisland Date: Wed, 10 Nov 2021 10:56:33 +0800 Subject: [PATCH 29/29] Fix wrong space --- qiling/utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qiling/utils.py b/qiling/utils.py index 1d40158e5..cf56bc24f 100644 --- a/qiling/utils.py +++ b/qiling/utils.py @@ -298,7 +298,6 @@ def ql_elf_parse_emu_env(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], elif e_machine == b"\xf3\x00" and elfbit == 2: archendian = QL_ENDIAN.EL arch = QL_ARCH.RISCV64 - return arch, ostype, archendian @@ -389,7 +388,7 @@ def ql_guess_emu_env(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], Opt if os.path.isfile(path) and path.endswith('.DOS_EXE'): return QL_ARCH.A8086, QL_OS.DOS, QL_ENDIAN.EL - arch, ostype, endian = ql_elf_parse_emu_env(path) + arch, ostype, endian = ql_elf_parse_emu_env(path) if arch is None or ostype is None or endian is None: arch, ostype, endian = ql_macho_parse_emu_env(path)