Introduce PowerPC architecture to qiling

This commit is contained in:
Bet4
2022-04-26 20:14:30 +08:00
parent 573ce1fafe
commit eec7db5379
19 changed files with 830 additions and 58 deletions
+1
View File
@@ -53,6 +53,7 @@
- madprogrammer
- danielmoos
- sigeryang
- bet4it
#### Legacy Core Developers
+1 -1
View File
@@ -13,7 +13,7 @@
Qiling is an advanced binary emulation framework, with the following features:
- Emulate multi-platforms: Windows, MacOS, Linux, BSD, UEFI, DOS, MBR, Ethereum Virtual Machine
- Emulate multi-architectures: X86, X86_64, Arm, Arm64, MIPS, 8086
- Emulate multi-architectures: 8086, X86, X86_64, ARM, ARM64, MIPS, RISCV, PowerPC
- Support multiple file formats: PE, MachO, ELF, COM, MBR
- Support Windows Driver (.sys), Linux Kernel Module (.ko) & MacOS Kernel (.kext) via [Demigod](https://groundx.io/demigod/)
- Emulates & sandbox code in an isolated environment
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from functools import cached_property
from unicorn import Uc, UC_ARCH_PPC, UC_MODE_PPC32, UC_MODE_BIG_ENDIAN
from capstone import Cs, CS_ARCH_PPC, CS_MODE_32, CS_MODE_BIG_ENDIAN
from keystone import Ks, KS_ARCH_PPC, KS_MODE_PPC32, KS_MODE_BIG_ENDIAN
from qiling import Qiling
from qiling.arch.arch import QlArch
from qiling.arch import ppc_const
from qiling.arch.register import QlRegisterManager
from qiling.const import QL_ARCH, QL_ENDIAN
class QlArchPPC(QlArch):
type = QL_ARCH.PPC
bits = 32
@cached_property
def uc(self) -> Uc:
return Uc(UC_ARCH_PPC, UC_MODE_PPC32 + UC_MODE_BIG_ENDIAN)
@cached_property
def regs(self) -> QlRegisterManager:
regs_map = dict(
**ppc_const.reg_map,
**ppc_const.reg_float_map
)
pc_reg = 'pc'
sp_reg = 'r1'
return QlRegisterManager(self.uc, regs_map, pc_reg, sp_reg)
@cached_property
def disassembler(self) -> Cs:
return Cs(CS_ARCH_PPC, CS_MODE_32 + CS_MODE_BIG_ENDIAN)
@cached_property
def assembler(self) -> Ks:
return Ks(KS_ARCH_PPC, KS_MODE_PPC32 + KS_MODE_BIG_ENDIAN)
@property
def endian(self) -> QL_ENDIAN:
return QL_ENDIAN.EB
def enable_float(self):
self.regs.msr = self.regs.msr | ppc_const.MSR.FP
+128
View File
@@ -0,0 +1,128 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from unicorn.ppc_const import *
from enum import IntEnum
reg_map = {
"r0": UC_PPC_REG_0,
"r1": UC_PPC_REG_1,
"r2": UC_PPC_REG_2,
"r3": UC_PPC_REG_3,
"r4": UC_PPC_REG_4,
"r5": UC_PPC_REG_5,
"r6": UC_PPC_REG_6,
"r7": UC_PPC_REG_7,
"r8": UC_PPC_REG_8,
"r9": UC_PPC_REG_9,
"r10": UC_PPC_REG_10,
"r11": UC_PPC_REG_11,
"r12": UC_PPC_REG_12,
"r13": UC_PPC_REG_13,
"r14": UC_PPC_REG_14,
"r15": UC_PPC_REG_15,
"r16": UC_PPC_REG_16,
"r17": UC_PPC_REG_17,
"r18": UC_PPC_REG_18,
"r19": UC_PPC_REG_19,
"r20": UC_PPC_REG_20,
"r21": UC_PPC_REG_21,
"r22": UC_PPC_REG_22,
"r23": UC_PPC_REG_23,
"r24": UC_PPC_REG_24,
"r25": UC_PPC_REG_25,
"r26": UC_PPC_REG_26,
"r27": UC_PPC_REG_27,
"r28": UC_PPC_REG_28,
"r29": UC_PPC_REG_29,
"r30": UC_PPC_REG_30,
"r31": UC_PPC_REG_31,
"pc": UC_PPC_REG_PC,
"msr": UC_PPC_REG_MSR,
"cr": UC_PPC_REG_CR0,
"lr": UC_PPC_REG_LR,
"ctr": UC_PPC_REG_CTR,
"xer": UC_PPC_REG_XER,
}
reg_float_map = {
"f0": UC_PPC_REG_FPR0,
"f1": UC_PPC_REG_FPR1,
"f2": UC_PPC_REG_FPR2,
"f3": UC_PPC_REG_FPR3,
"f4": UC_PPC_REG_FPR4,
"f5": UC_PPC_REG_FPR5,
"f6": UC_PPC_REG_FPR6,
"f7": UC_PPC_REG_FPR7,
"f8": UC_PPC_REG_FPR8,
"f9": UC_PPC_REG_FPR9,
"f10": UC_PPC_REG_FPR10,
"f11": UC_PPC_REG_FPR11,
"f12": UC_PPC_REG_FPR12,
"f13": UC_PPC_REG_FPR13,
"f14": UC_PPC_REG_FPR14,
"f15": UC_PPC_REG_FPR15,
"f16": UC_PPC_REG_FPR16,
"f17": UC_PPC_REG_FPR17,
"f18": UC_PPC_REG_FPR18,
"f19": UC_PPC_REG_FPR19,
"f20": UC_PPC_REG_FPR20,
"f21": UC_PPC_REG_FPR21,
"f22": UC_PPC_REG_FPR22,
"f23": UC_PPC_REG_FPR23,
"f24": UC_PPC_REG_FPR24,
"f25": UC_PPC_REG_FPR25,
"f26": UC_PPC_REG_FPR26,
"f27": UC_PPC_REG_FPR27,
"f28": UC_PPC_REG_FPR28,
"f29": UC_PPC_REG_FPR29,
"f30": UC_PPC_REG_FPR30,
"f31": UC_PPC_REG_FPR31,
}
class MSR(IntEnum):
SF = 1 << 63
TAG = 1 << 62
ISF = 1 << 61
HV = 1 << 60
TS0 = 1 << 34
TS1 = 1 << 33
TM = 1 << 32
CM = 1 << 31
ICM = 1 << 30
GS = 1 << 28
UCLE = 1 << 26
VR = 1 << 25
SPE = 1 << 25
AP = 1 << 23
VSX = 1 << 23
SA = 1 << 22
KEY = 1 << 19
POW = 1 << 18
TGPR = 1 << 17
CE = 1 << 17
ILE = 1 << 16
EE = 1 << 15
PR = 1 << 14
FP = 1 << 13
ME = 1 << 12
FE0 = 1 << 11
SE = 1 << 10
DWE = 1 << 10
UBLE = 1 << 10
BE = 1 << 9
DE = 1 << 9
FE1 = 1 << 8
AL = 1 << 7
EP = 1 << 6
IR = 1 << 5
DR = 1 << 4
IS = 1 << 5
DS = 1 << 4
PE = 1 << 3
PX = 1 << 2
PMM = 1 << 2
RI = 1 << 1
LE = 1 << 0
+4 -3
View File
@@ -11,8 +11,8 @@ from typing import Tuple
from os.path import basename
from functools import lru_cache
from keystone import (Ks, KS_ARCH_ARM, KS_ARCH_ARM64, KS_ARCH_MIPS, KS_ARCH_X86,
KS_MODE_ARM, KS_MODE_THUMB, KS_MODE_MIPS32, KS_MODE_16, KS_MODE_32, KS_MODE_64,
from keystone import (Ks, KS_ARCH_ARM, KS_ARCH_ARM64, KS_ARCH_MIPS, KS_ARCH_X86, KS_ARCH_PPC,
KS_MODE_ARM, KS_MODE_THUMB, KS_MODE_MIPS32, KS_MODE_PPC32, KS_MODE_16, KS_MODE_32, KS_MODE_64,
KS_MODE_LITTLE_ENDIAN, KS_MODE_BIG_ENDIAN)
from qiling import Qiling
@@ -104,7 +104,8 @@ def assembler(arch: QL_ARCH, endianess: QL_ENDIAN, is_thumb: bool) -> Ks:
QL_ARCH.MIPS : (KS_ARCH_MIPS, KS_MODE_MIPS32 + endian),
QL_ARCH.A8086 : (KS_ARCH_X86, KS_MODE_16),
QL_ARCH.X86 : (KS_ARCH_X86, KS_MODE_32),
QL_ARCH.X8664 : (KS_ARCH_X86, KS_MODE_64)
QL_ARCH.X8664 : (KS_ARCH_X86, KS_MODE_64),
QL_ARCH.PPC : (KS_ARCH_PPC, KS_MODE_PPC32 + KS_MODE_BIG_ENDIAN)
}
if arch in asm_map:
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
from qiling.cc import QlCommonBaseCC
from unicorn.ppc_const import (
UC_PPC_REG_3, UC_PPC_REG_4, UC_PPC_REG_5,
UC_PPC_REG_6, UC_PPC_REG_7, UC_PPC_REG_8,
)
class ppc(QlCommonBaseCC):
"""Default calling convention for PPC
First 6 arguments are passed in regs, the rest are passed on the stack.
"""
_retreg = UC_PPC_REG_3
_argregs = (UC_PPC_REG_3, UC_PPC_REG_4, UC_PPC_REG_5, UC_PPC_REG_6, UC_PPC_REG_7, UC_PPC_REG_8) + (None, ) * 10
@staticmethod
def getNumSlots(argbits: int):
return 1
+1
View File
@@ -21,6 +21,7 @@ class QL_ARCH(IntEnum):
CORTEX_M = 109
RISCV = 110
RISCV64 = 111
PPC = 112
class QL_OS(IntEnum):
LINUX = 201
+9 -6
View File
@@ -4,7 +4,7 @@
#
from qiling import Qiling
from qiling.cc import QlCC, intel, arm, mips
from qiling.cc import QlCC, intel, arm, mips, riscv, ppc
from qiling.const import QL_ARCH, QL_OS
from qiling.os.fcall import QlFunctionCall
from qiling.os.os import QlOs
@@ -26,11 +26,14 @@ class QlOsBlob(QlOs):
self.ql = ql
cc: QlCC = {
QL_ARCH.X86 : intel.cdecl,
QL_ARCH.X8664 : intel.amd64,
QL_ARCH.ARM : arm.aarch32,
QL_ARCH.ARM64 : arm.aarch64,
QL_ARCH.MIPS : mips.mipso32
QL_ARCH.X86 : intel.cdecl,
QL_ARCH.X8664 : intel.amd64,
QL_ARCH.ARM : arm.aarch32,
QL_ARCH.ARM64 : arm.aarch64,
QL_ARCH.MIPS : mips.mipso32,
QL_ARCH.RISCV : riscv.riscv,
QL_ARCH.RISCV64 : riscv.riscv,
QL_ARCH.PPC : ppc.ppc,
}[ql.arch.type](ql.arch)
self.fcall = QlFunctionCall(ql, cc)
+21 -24
View File
@@ -79,6 +79,10 @@ class HookFunc:
elif self.ql.arch.type == QL_ARCH.ARM64:
return self.ql.arch.regs.x30
# PPC
elif self.ql.arch.type== QL_ARCH.PPC:
return self.ql.arch.regs.lr
# X86
elif self.ql.arch.type == QL_ARCH.X86:
return self.ql.unpack(self.ql.mem.read(self.ql.arch.regs.esp, self.ql.arch.pointersize))
@@ -98,6 +102,10 @@ class HookFunc:
elif self.ql.arch.type == QL_ARCH.MIPS:
pass
# PPC
elif self.ql.arch.type== QL_ARCH.PPC:
pass
# ARM64
elif self.ql.arch.type == QL_ARCH.ARM64:
pass
@@ -121,6 +129,10 @@ class HookFunc:
elif self.ql.arch.type == QL_ARCH.MIPS:
self.ql.arch.regs.ra = addr
# PPC
elif self.ql.arch.type== QL_ARCH.PPC:
self.ql.arch.regs.lr = addr
# ARM64
elif self.ql.arch.type == QL_ARCH.ARM64:
self.ql.arch.stack_write(0, addr)
@@ -173,29 +185,6 @@ class HookFunc:
else:
self.context_fixup()
def ret(self):
# ARM
if self.ql.arch.type == QL_ARCH.ARM:
self.ql.arch.regs.arch_pc = self.ret_pc
# MIPS32
elif self.ql.arch.type == QL_ARCH.MIPS:
self.ql.arch.regs.arch_pc = self.ret_pc
# ARM64
elif self.ql.arch.type == QL_ARCH.ARM64:
self.ql.arch.regs.arch_pc = self.ret_pc
# X86
elif self.ql.arch.type == QL_ARCH.X86:
self.ql.arch.regs.arch_pc = self.ret_pc
# X8664
elif self.ql.arch.type == QL_ARCH.X8664:
self.ql.arch.regs.arch_pc = self.ret_pc
else:
raise
def call_exit(self):
# if self.ql.arch.type == QL_ARCH.ARM or self.ql.arch.type == QL_ARCH.ARM64:
# self.ql.arch.regs.arch_pc = self.ql.arch.regs.arch_pc + 4
@@ -211,7 +200,7 @@ class HookFunc:
else:
onexit_cb(self.ql, onexit_userdata)
self.ret()
self.ql.arch.regs.arch_pc = self.ret_pc
class HookFuncRel(HookFunc):
@@ -614,6 +603,14 @@ class FunctionHook:
ins = b'\x00\x01'
self.add_function_hook = self.add_function_hook_relocation
# PowerPC
elif self.ql.arch.type== QL_ARCH.PPC:
self.GLOB_DAT = 21
self.JMP_SLOT = 22
# nop
ins = b'\x60\x00\x00\x00'
self.add_function_hook = self.add_function_hook_relocation
self._parse()
if self.rel != None:
self.show_relocation(self.rel)
+14 -8
View File
@@ -10,7 +10,7 @@ from qiling import Qiling
from qiling.arch.x86_const import GS_SEGMENT_ADDR, GS_SEGMENT_SIZE
from qiling.arch.x86_utils import GDTManager, SegmentManager86, SegmentManager64
from qiling.arch import arm_utils
from qiling.cc import QlCC, intel, arm, mips, riscv
from qiling.cc import QlCC, intel, arm, mips, riscv, ppc
from qiling.const import QL_ARCH, QL_OS
from qiling.os.fcall import QlFunctionCall
from qiling.os.const import *
@@ -28,13 +28,14 @@ class QlOsLinux(QlOsPosix):
self.ql = ql
cc: QlCC = {
QL_ARCH.X86 : intel.cdecl,
QL_ARCH.X8664 : intel.amd64,
QL_ARCH.ARM : arm.aarch32,
QL_ARCH.ARM64 : arm.aarch64,
QL_ARCH.MIPS : mips.mipso32,
QL_ARCH.RISCV : riscv.riscv,
QL_ARCH.RISCV64: riscv.riscv,
QL_ARCH.X86 : intel.cdecl,
QL_ARCH.X8664 : intel.amd64,
QL_ARCH.ARM : arm.aarch32,
QL_ARCH.ARM64 : arm.aarch64,
QL_ARCH.MIPS : mips.mipso32,
QL_ARCH.RISCV : riscv.riscv,
QL_ARCH.RISCV64 : riscv.riscv,
QL_ARCH.PPC : ppc.ppc,
}[ql.arch.type](ql.arch)
self.fcall = QlFunctionCall(ql, cc)
@@ -107,6 +108,11 @@ class QlOsLinux(QlOsPosix):
self.ql.hook_intno(self.hook_syscall, 8)
self.thread_class = None
elif self.ql.arch.type == QL_ARCH.PPC:
self.ql.arch.enable_float()
self.ql.hook_intno(self.hook_syscall, 8)
self.thread_class = None
# on fork or execve, do not inherit opened files tagged as 'close on exec'
for i in range(len(self.fd)):
if getattr(self.fd[i], 'close_on_exec', 0):
+421 -2
View File
@@ -18,8 +18,9 @@ def get_syscall_mapper(archtype: QL_ARCH):
QL_ARCH.X8664 : x8664_syscall_table,
QL_ARCH.X86 : x86_syscall_table,
QL_ARCH.MIPS : mips_syscall_table,
QL_ARCH.RISCV : riscv32_syscall_table,
QL_ARCH.RISCV64 : riscv64_syscall_table
QL_ARCH.RISCV : riscv32_syscall_table,
QL_ARCH.RISCV64 : riscv64_syscall_table,
QL_ARCH.PPC : ppc_syscall_table
}[archtype]
def __mapper(syscall_num: int) -> str:
@@ -2550,3 +2551,421 @@ riscv64_syscall_table = {
446: "landlock_restrict_self",
448: "process_mrelease",
}
ppc_syscall_table = {
0: "restart_syscall",
1: "exit",
2: "fork",
3: "read",
4: "write",
5: "open",
6: "close",
7: "waitpid",
8: "creat",
9: "link",
10: "unlink",
11: "execve",
12: "chdir",
13: "time",
14: "mknod",
15: "chmod",
16: "lchown",
17: "break",
18: "oldstat",
19: "lseek",
20: "getpid",
21: "mount",
22: "umount",
23: "setuid",
24: "getuid",
25: "stime",
26: "ptrace",
27: "alarm",
28: "oldfstat",
29: "pause",
30: "utime",
31: "stty",
32: "gtty",
33: "access",
34: "nice",
35: "ftime",
36: "sync",
37: "kill",
38: "rename",
39: "mkdir",
40: "rmdir",
41: "dup",
42: "pipe",
43: "times",
44: "prof",
45: "brk",
46: "setgid",
47: "getgid",
48: "signal",
49: "geteuid",
50: "getegid",
51: "acct",
52: "umount2",
53: "lock",
54: "ioctl",
55: "fcntl",
56: "mpx",
57: "setpgid",
58: "ulimit",
59: "oldolduname",
60: "umask",
61: "chroot",
62: "ustat",
63: "dup2",
64: "getppid",
65: "getpgrp",
66: "setsid",
67: "sigaction",
68: "sgetmask",
69: "ssetmask",
70: "setreuid",
71: "setregid",
72: "sigsuspend",
73: "sigpending",
74: "sethostname",
75: "setrlimit",
76: "getrlimit",
77: "getrusage",
78: "gettimeofday",
79: "settimeofday",
80: "getgroups",
81: "setgroups",
82: "select",
83: "symlink",
84: "oldlstat",
85: "readlink",
86: "uselib",
87: "swapon",
88: "reboot",
89: "readdir",
90: "mmap",
91: "munmap",
92: "truncate",
93: "ftruncate",
94: "fchmod",
95: "fchown",
96: "getpriority",
97: "setpriority",
98: "profil",
99: "statfs",
100: "fstatfs",
101: "ioperm",
102: "socketcall",
103: "syslog",
104: "setitimer",
105: "getitimer",
106: "stat",
107: "lstat",
108: "fstat",
109: "olduname",
110: "iopl",
111: "vhangup",
112: "idle",
113: "vm86",
114: "wait4",
115: "swapoff",
116: "sysinfo",
117: "ipc",
118: "fsync",
119: "sigreturn",
120: "clone",
121: "setdomainname",
122: "uname",
123: "modify_ldt",
124: "adjtimex",
125: "mprotect",
126: "sigprocmask",
127: "create_module",
128: "init_module",
129: "delete_module",
130: "get_kernel_syms",
131: "quotactl",
132: "getpgid",
133: "fchdir",
134: "bdflush",
135: "sysfs",
136: "personality",
137: "afs_syscall",
138: "setfsuid",
139: "setfsgid",
140: "_llseek",
141: "getdents",
142: "_newselect",
143: "flock",
144: "msync",
145: "readv",
146: "writev",
147: "getsid",
148: "fdatasync",
149: "_sysctl",
150: "mlock",
151: "munlock",
152: "mlockall",
153: "munlockall",
154: "sched_setparam",
155: "sched_getparam",
156: "sched_setscheduler",
157: "sched_getscheduler",
158: "sched_yield",
159: "sched_get_priority_max",
160: "sched_get_priority_min",
161: "sched_rr_get_interval",
162: "nanosleep",
163: "mremap",
164: "setresuid",
165: "getresuid",
166: "query_module",
167: "poll",
168: "nfsservctl",
169: "setresgid",
170: "getresgid",
171: "prctl",
172: "rt_sigreturn",
173: "rt_sigaction",
174: "rt_sigprocmask",
175: "rt_sigpending",
176: "rt_sigtimedwait",
177: "rt_sigqueueinfo",
178: "rt_sigsuspend",
179: "pread64",
180: "pwrite64",
181: "chown",
182: "getcwd",
183: "capget",
184: "capset",
185: "sigaltstack",
186: "sendfile",
187: "getpmsg",
188: "putpmsg",
189: "vfork",
190: "ugetrlimit",
191: "readahead",
192: "mmap2",
193: "truncate64",
194: "ftruncate64",
195: "stat64",
196: "lstat64",
197: "fstat64",
198: "pciconfig_read",
199: "pciconfig_write",
200: "pciconfig_iobase",
201: "multiplexer",
202: "getdents64",
203: "pivot_root",
204: "fcntl64",
205: "madvise",
206: "mincore",
207: "gettid",
208: "tkill",
209: "setxattr",
210: "lsetxattr",
211: "fsetxattr",
212: "getxattr",
213: "lgetxattr",
214: "fgetxattr",
215: "listxattr",
216: "llistxattr",
217: "flistxattr",
218: "removexattr",
219: "lremovexattr",
220: "fremovexattr",
221: "futex",
222: "sched_setaffinity",
223: "sched_getaffinity",
225: "tuxcall",
226: "sendfile64",
227: "io_setup",
228: "io_destroy",
229: "io_getevents",
230: "io_submit",
231: "io_cancel",
232: "set_tid_address",
233: "fadvise64",
234: "exit_group",
235: "lookup_dcookie",
236: "epoll_create",
237: "epoll_ctl",
238: "epoll_wait",
239: "remap_file_pages",
240: "timer_create",
241: "timer_settime",
242: "timer_gettime",
243: "timer_getoverrun",
244: "timer_delete",
245: "clock_settime",
246: "clock_gettime",
247: "clock_getres",
248: "clock_nanosleep",
249: "swapcontext",
250: "tgkill",
251: "utimes",
252: "statfs64",
253: "fstatfs64",
254: "fadvise64_64",
255: "rtas",
256: "sys_debug_setcontext",
258: "migrate_pages",
259: "mbind",
260: "get_mempolicy",
261: "set_mempolicy",
262: "mq_open",
263: "mq_unlink",
264: "mq_timedsend",
265: "mq_timedreceive",
266: "mq_notify",
267: "mq_getsetattr",
268: "kexec_load",
269: "add_key",
270: "request_key",
271: "keyctl",
272: "waitid",
273: "ioprio_set",
274: "ioprio_get",
275: "inotify_init",
276: "inotify_add_watch",
277: "inotify_rm_watch",
278: "spu_run",
279: "spu_create",
280: "pselect6",
281: "ppoll",
282: "unshare",
283: "splice",
284: "tee",
285: "vmsplice",
286: "openat",
287: "mkdirat",
288: "mknodat",
289: "fchownat",
290: "futimesat",
291: "fstatat64",
292: "unlinkat",
293: "renameat",
294: "linkat",
295: "symlinkat",
296: "readlinkat",
297: "fchmodat",
298: "faccessat",
299: "get_robust_list",
300: "set_robust_list",
301: "move_pages",
302: "getcpu",
303: "epoll_pwait",
304: "utimensat",
305: "signalfd",
306: "timerfd_create",
307: "eventfd",
308: "sync_file_range2",
309: "fallocate",
310: "subpage_prot",
311: "timerfd_settime",
312: "timerfd_gettime",
313: "signalfd4",
314: "eventfd2",
315: "epoll_create1",
316: "dup3",
317: "pipe2",
318: "inotify_init1",
319: "perf_event_open",
320: "preadv",
321: "pwritev",
322: "rt_tgsigqueueinfo",
323: "fanotify_init",
324: "fanotify_mark",
325: "prlimit64",
326: "socket",
327: "bind",
328: "connect",
329: "listen",
330: "accept",
331: "getsockname",
332: "getpeername",
333: "socketpair",
334: "send",
335: "sendto",
336: "recv",
337: "recvfrom",
338: "shutdown",
339: "setsockopt",
340: "getsockopt",
341: "sendmsg",
342: "recvmsg",
343: "recvmmsg",
344: "accept4",
345: "name_to_handle_at",
346: "open_by_handle_at",
347: "clock_adjtime",
348: "syncfs",
349: "sendmmsg",
350: "setns",
351: "process_vm_readv",
352: "process_vm_writev",
353: "finit_module",
354: "kcmp",
355: "sched_setattr",
356: "sched_getattr",
357: "renameat2",
358: "seccomp",
359: "getrandom",
360: "memfd_create",
361: "bpf",
362: "execveat",
363: "switch_endian",
364: "userfaultfd",
365: "membarrier",
378: "mlock2",
379: "copy_file_range",
380: "preadv2",
381: "pwritev2",
382: "kexec_file_load",
383: "statx",
384: "pkey_alloc",
385: "pkey_free",
386: "pkey_mprotect",
387: "rseq",
388: "io_pgetevents",
393: "semget",
394: "semctl",
395: "shmget",
396: "shmctl",
397: "shmat",
398: "shmdt",
399: "msgget",
400: "msgsnd",
401: "msgrcv",
402: "msgctl",
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",
}
+18
View File
@@ -515,6 +515,24 @@ linux_riscv_open_flags = {
'O_LARGEFILE': None,
}
linux_ppc_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': 0x8000,
'O_CREAT': 0x40,
'O_TRUNC': 0x200,
'O_EXCL': 0x80,
'O_NOCTTY': 0x100,
'O_DIRECTORY': 0x4000,
'O_BINARY' : None,
'O_LARGEFILE': 0x10000,
}
freebsd_x86_open_flags = {
'O_RDONLY': 0x0,
'O_WRONLY': 0x1,
+2
View File
@@ -61,6 +61,8 @@ def ql_open_flag_mapping(ql: Qiling, flags):
f = linux_mips_open_flags
elif ql.arch.type in (QL_ARCH.RISCV, QL_ARCH.RISCV64):
f = linux_riscv_open_flags
elif ql.arch.type == QL_ARCH.PPC:
f = linux_ppc_open_flags
elif virt_os == QL_OS.MACOS:
if ql.arch.type in (QL_ARCH.X86, QL_ARCH.X8664):
+9 -3
View File
@@ -19,9 +19,10 @@ from unicorn.x86_const import (
UC_X86_REG_R9, UC_X86_REG_RAX
)
from unicorn.riscv_const import UC_RISCV_REG_A7
from unicorn.ppc_const import UC_PPC_REG_0
from qiling import Qiling
from qiling.cc import QlCC, intel, arm, mips, riscv
from qiling.cc import QlCC, intel, arm, mips, riscv, ppc
from qiling.const import QL_ARCH, QL_OS, QL_INTERCEPT
from qiling.exception import QlErrorSyscallNotFound
from qiling.os.os import QlOs
@@ -60,6 +61,9 @@ class riscv32(riscv.riscv):
class riscv64(riscv.riscv):
pass
class ppc(ppc.ppc):
pass
class QlFileDes:
def __init__(self):
@@ -115,7 +119,8 @@ class QlOsPosix(QlOs):
QL_ARCH.X86 : UC_X86_REG_EAX,
QL_ARCH.X8664 : UC_X86_REG_RAX,
QL_ARCH.RISCV : UC_RISCV_REG_A7,
QL_ARCH.RISCV64 : UC_RISCV_REG_A7
QL_ARCH.RISCV64 : UC_RISCV_REG_A7,
QL_ARCH.PPC : UC_PPC_REG_0
}[self.ql.arch.type]
# handle some special cases
@@ -133,7 +138,8 @@ class QlOsPosix(QlOs):
QL_ARCH.X86 : intel32,
QL_ARCH.X8664 : intel64,
QL_ARCH.RISCV : riscv32,
QL_ARCH.RISCV64 : riscv64
QL_ARCH.RISCV64 : riscv64,
QL_ARCH.PPC : ppc
}[self.ql.arch.type](self.ql.arch)
# select syscall mapping function based on emulated OS and architecture
+106
View File
@@ -819,6 +819,108 @@ class LinuxRISCVStat(ctypes.Structure):
_pack_ = 8
# Srouce: https://elixir.bootlin.com/linux/latest/source/arch/powerpc/include/uapi/asm/stat.h#L30
# struct stat {
# unsigned long st_dev;
# ino_t st_ino;
# #ifdef __powerpc64__
# unsigned long st_nlink;
# mode_t st_mode;
# #else
# mode_t st_mode;
# unsigned short st_nlink;
# #endif
# uid_t st_uid;
# gid_t st_gid;
# unsigned long st_rdev;
# long st_size;
# unsigned long st_blksize;
# unsigned long st_blocks;
# unsigned long st_atime;
# unsigned long st_atime_nsec;
# unsigned long st_mtime;
# unsigned long st_mtime_nsec;
# unsigned long st_ctime;
# unsigned long st_ctime_nsec;
# unsigned long __unused4;
# unsigned long __unused5;
# #ifdef __powerpc64__
# unsigned long __unused6;
# #endif
# };
class LinuxPPCStat(ctypes.BigEndianStructure):
_fields_ = [
("st_dev", ctypes.c_uint32),
("st_ino", ctypes.c_uint32),
("st_mode", ctypes.c_uint32),
("st_nlink", ctypes.c_uint16),
("st_uid", ctypes.c_uint32),
("st_gid", ctypes.c_uint32),
("st_rdev", ctypes.c_uint32),
("st_size", ctypes.c_uint32),
("st_blksize", ctypes.c_uint32),
("st_blocks", ctypes.c_uint32),
("st_atime", ctypes.c_uint32),
("st_atime_ns", ctypes.c_uint32),
("st_mtime", ctypes.c_uint32),
("st_mtime_ns", ctypes.c_uint32),
("st_ctime", ctypes.c_uint32),
("st_ctime_ns", ctypes.c_uint32),
("__unused4", ctypes.c_uint32),
("__unused5", ctypes.c_uint32)
]
_pack_ = 8
# Srouce: https://elixir.bootlin.com/linux/latest/source/arch/powerpc/include/uapi/asm/stat.h#L60
# struct stat64 {
# unsigned long long st_dev; /* Device. */
# unsigned long 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 long st_rdev; /* Device number, if device. */
# unsigned short __pad2;
# long long st_size; /* Size of file, in bytes. */
# int st_blksize; /* Optimal block size for I/O. */
# long long st_blocks; /* Number 512-byte blocks allocated. */
# int st_atime; /* Time of last access. */
# unsigned int st_atime_nsec;
# int st_mtime; /* Time of last modification. */
# unsigned int st_mtime_nsec;
# int st_ctime; /* Time of last status change. */
# unsigned int st_ctime_nsec;
# unsigned int __unused4;
# unsigned int __unused5;
# };
class LinuxPPCStat64(ctypes.BigEndianStructure):
_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),
("__pad2", ctypes.c_uint16),
("st_size", ctypes.c_uint64),
("st_blksize", ctypes.c_uint32),
("st_blocks", ctypes.c_uint64),
("st_atime", ctypes.c_uint32),
("st_atime_ns", ctypes.c_uint32),
("st_mtime", ctypes.c_uint32),
("st_mtime_ns", ctypes.c_uint32),
("st_ctime", ctypes.c_uint32),
("st_ctime_ns", ctypes.c_uint32),
("__unused4", ctypes.c_uint32),
("__unused5", ctypes.c_uint32)
]
_pack_ = 8
# Source: openqnx lib/c/public/sys/stat.h
#
# struct stat {
@@ -991,6 +1093,8 @@ def get_stat64_struct(ql: Qiling):
return LinuxARMStat64()
elif ql.arch.type in (QL_ARCH.RISCV, QL_ARCH.RISCV64):
return LinuxRISCVStat()
elif ql.arch.type == QL_ARCH.PPC:
return LinuxPPCStat64()
elif ql.os.type == QL_OS.MACOS:
return MacOSStat64()
elif ql.os.type == QL_OS.QNX:
@@ -1034,6 +1138,8 @@ def get_stat_struct(ql: Qiling):
return LinuxARM64EBStat()
elif ql.arch.type in (QL_ARCH.RISCV, QL_ARCH.RISCV64):
return LinuxRISCVStat()
elif ql.archtype == QL_ARCH.PPC:
return LinuxPPCStat()
elif ql.os.type == QL_OS.QNX:
if ql.arch.type == QL_ARCH.ARM64:
return QNXARM64Stat()
+9 -8
View File
@@ -14,7 +14,7 @@ from qiling.os.qnx.const import NTO_SIDE_CHANNEL, SYSMGR_PID, SYSMGR_CHID, SYSMG
from qiling.os.qnx.helpers import QnxConn
from qiling.os.qnx.structs import _thread_local_storage
from qiling.cc import QlCC, intel, arm, mips, riscv
from qiling.cc import QlCC, intel, arm, mips, riscv, ppc
from qiling.const import QL_ARCH, QL_OS
from qiling.os.fcall import QlFunctionCall
from qiling.os.const import *
@@ -29,13 +29,14 @@ class QlOsQnx(QlOsPosix):
self.ql = ql
cc: QlCC = {
QL_ARCH.X86 : intel.cdecl,
QL_ARCH.X8664 : intel.amd64,
QL_ARCH.ARM : arm.aarch32,
QL_ARCH.ARM64 : arm.aarch64,
QL_ARCH.MIPS : mips.mipso32,
QL_ARCH.RISCV : riscv.riscv,
QL_ARCH.RISCV64: riscv.riscv,
QL_ARCH.X86 : intel.cdecl,
QL_ARCH.X8664 : intel.amd64,
QL_ARCH.ARM : arm.aarch32,
QL_ARCH.ARM64 : arm.aarch64,
QL_ARCH.MIPS : mips.mipso32,
QL_ARCH.RISCV : riscv.riscv,
QL_ARCH.RISCV64 : riscv.riscv,
QL_ARCH.PPC : ppc.ppc,
}[ql.arch.type](ql.arch)
self.fcall = QlFunctionCall(ql, cc)
+5 -2
View File
@@ -126,6 +126,7 @@ def __emu_env_from_elf(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], O
EM_X86_64 = 62
EM_AARCH64 = 183
EM_RISCV = 243
EM_PPC = 20
endianess = {
ELFDATA2LSB : (QL_ENDIAN.EL, 'little'),
@@ -136,7 +137,8 @@ def __emu_env_from_elf(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], O
EM_386 : QL_ARCH.X86,
EM_MIPS : QL_ARCH.MIPS,
EM_ARM : QL_ARCH.ARM,
EM_RISCV : QL_ARCH.RISCV
EM_RISCV : QL_ARCH.RISCV,
EM_PPC : QL_ARCH.PPC
}
machines64 = {
@@ -381,7 +383,8 @@ def select_arch(archtype: QL_ARCH, endian: QL_ENDIAN, thumb: bool) -> QlClassIni
QL_ARCH.EVM : r'evm.evm',
QL_ARCH.CORTEX_M : r'cortex_m',
QL_ARCH.RISCV : r'riscv',
QL_ARCH.RISCV64 : r'riscv64'
QL_ARCH.RISCV64 : r'riscv64',
QL_ARCH.PPC : r'ppc'
}[archtype]
qlarch_path = f'.arch.{module}'
+6
View File
@@ -820,6 +820,12 @@ class ELFTest(unittest.TestCase):
del ql
def test_elf_linux_powerpc(self):
ql = Qiling(["../examples/rootfs/powerpc_linux/bin/powerpc_hello"], "../examples/rootfs/powerpc_linux", verbose=QL_VERBOSE.DEBUG)
ql.run()
del ql
def test_elf_linux_arm_custom_syscall(self):
def my_syscall_write(ql, write_fd, write_buf, write_count, *args, **kw):
regreturn = 0