6 from core
.operating_system
import Armv8_RegisterSet
, Armv7_RegisterSet
, I386_RegisterSet
, X86_64RegisterSet
8 CPU_TYPE_I386
= 0x00000007
9 CPU_TYPE_X86_64
= 0x01000007
10 CPU_TYPE_ARM
= 0x0000000c
11 CPU_TYPE_ARM64
= 0x0100000c
14 CPU_SUBTYPE_X86_64_ALL
= 3
15 CPU_SUBTYPE_X86_64_H
= 8
16 CPU_SUBTYPE_ARMV8
= 13
17 CPU_SUBTYPE_ARM_V7
= 9
18 CPU_SUBTYPE_ARM_V7S
= 11
19 CPU_SUBTYPE_ARM_V7K
= 12
22 def GetRegisterSetForCPU(cputype
, subtype
):
23 retval
= X86_64RegisterSet
24 if cputype
in (CPU_TYPE_ARM
, CPU_TYPE_ARM64
):
25 if subtype
== CPU_SUBTYPE_ARMV8
:
26 retval
= Armv8_RegisterSet
28 retval
= Armv7_RegisterSet
29 elif cputype
== CPU_TYPE_I386
:
30 retval
= I386_RegisterSet
32 return retval
.register_info
['registers']
35 class UserThreadObject(object):
36 """representation of userspace thread"""
37 def __init__(self
, thr_obj
, cputype
, cpusubtype
, kern_cputype
):
38 super(UserThreadObject
, self
).__init
__()
40 self
.registerset
= GetRegisterSetForCPU(cputype
, cpusubtype
)
41 self
.thread_id
= unsigned(self
.thread
.thread_id
)
42 self
.is64Bit
= bool(cputype
& 0x01000000)
43 isKern64Bit
= bool(kern_cputype
& 0x01000000)
46 if cputype
== CPU_TYPE_X86_64
:
47 self
.reg_type
= "x86_64"
48 self
.saved_state
= Cast(self
.thread
.machine
.iss
, 'x86_saved_state_t *').uss
.ss_64
49 if cputype
== CPU_TYPE_ARM64
:
50 self
.reg_type
= "arm64"
51 self
.saved_state
= self
.thread
.machine
.upcb
.uss
.ss_64
53 if cputype
== CPU_TYPE_I386
:
54 self
.reg_type
= "i386"
55 self
.saved_state
= Cast(self
.thread
.machine
.iss
, 'x86_saved_state_t *').uss
.ss_32
56 if cputype
== CPU_TYPE_ARM
:
59 self
.saved_state
= self
.thread
.machine
.PcbData
61 self
.saved_state
= self
.thread
.machine
.contextData
.ss
.uss
.ss_32
62 logging
.debug("created thread id 0x%x of type %s, kern_cputype 0x%x cputype 0x%x"
63 % (self
.thread_id
, self
.reg_type
, kern_cputype
, cputype
))
65 def getRegisterValueByName(self
, name
):
66 if self
.reg_type
== 'arm64':
67 if name
in ('x0', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10', 'x11', 'x12', 'x13', 'x14', 'x15', 'x16', 'x17', 'x18', 'x19', 'x20', 'x21', 'x22', 'x23', 'x24', 'x25', 'x26', 'x27', 'x28'):
68 return unsigned(getattr(self
.saved_state
, 'x')[int(name
.strip('x'))])
70 return unsigned(getattr(self
.saved_state
, name
))
72 if self
.reg_type
== "x86_64":
73 if name
in ('rip', 'rflags', 'cs', 'rsp', 'cpu'):
74 return unsigned(getattr(self
.saved_state
.isf
, name
))
75 return unsigned(getattr(self
.saved_state
, name
))
77 if self
.reg_type
== "arm":
78 if name
in ('r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10', 'r11', 'r12'):
79 retval
= unsigned(getattr(self
.saved_state
, 'r')[int(name
.strip('r'))])
81 retval
= unsigned(getattr(self
.saved_state
, name
))
87 return str(self
.thread_id
)
89 def getRegisterData(self
, reg_num
):
90 """ returns None if there is error """
91 if reg_num
< 0 or reg_num
>= len(self
.registerset
):
92 logging
.warning("regnum %d is not defined for thread_id 0x%x" % (reg_num
, self
.thread_id
))
94 return self
.getRegisterValueByName(self
.registerset
[reg_num
]['name'])
97 class UserProcess(target
.Process
):
98 """ Represent a user process and thread states """
99 def __init__(self
, task
):
101 self
.proc
= Cast(task
.bsd_info
, 'proc_t')
102 dataregisters64bit
= False
105 if task
.t_flags
& 0x1:
107 if task
.t_flags
& 0x2:
108 dataregisters64bit
= 8
110 cputype
= CPU_TYPE_X86_64
111 cpusubtype
= CPU_SUBTYPE_X86_64_ALL
113 if kern
.arch
in ('arm'):
114 cputype
= CPU_TYPE_ARM
115 cpusubtype
= CPU_SUBTYPE_ARM_V7
116 elif kern
.arch
in ('armv8', 'arm64'):
117 cputype
= CPU_TYPE_ARM64
118 cpusubtype
= CPU_SUBTYPE_ARMV8
120 super(UserProcess
, self
).__init
__(cputype
, cpusubtype
, ptrsize
)
122 self
.hinfo
['ostype'] = 'macosx'
123 if cputype
!= CPU_TYPE_X86_64
:
124 self
.hinfo
['ostype'] = 'ios'
126 self
.cputype
= unsigned(self
.proc
.p_cputype
)
127 self
.cpusubtype
= unsigned(self
.proc
.p_cpusubtype
)
128 self
.registerset
= GetRegisterSetForCPU(cputype
, cpusubtype
)
129 logging
.debug("process %s is64bit: %d ptrsize: %d cputype: %d cpusubtype:%d",
130 hex(self
.proc
), int(dataregisters64bit
), ptrsize
,
131 self
.cputype
, self
.cpusubtype
134 self
.threads_ids_list
= []
135 logging
.debug("iterating over threads in process")
136 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
137 self
.threads
[unsigned(thval
.thread_id
)] = UserThreadObject(thval
, self
.cputype
, self
.cpusubtype
, cputype
)
138 self
.threads_ids_list
.append(unsigned(thval
.thread_id
))
140 def getRegisterDataForThread(self
, th_id
, reg_num
):
141 if th_id
not in self
.threads
:
142 logging
.critical("0x%x thread id is not found in this task")
144 if reg_num
< 0 or reg_num
>= len(self
.registerset
):
145 logging
.warning("regnum %d is not defined for thread_id 0x%x" % (reg_num
, th_id
))
147 value
= self
.threads
[th_id
].getRegisterData(reg_num
)
148 return self
.encodeRegisterData(value
, bytesize
=self
.registerset
[reg_num
]['bitsize']/8)
150 def getRegisterCombinedDataForThread(self
, th_id
):
151 if th_id
not in self
.threads
:
152 logging
.critical("0x%x thread id is not found in this task" % th_id
)
154 cur_thread
= self
.threads
[th_id
]
155 retval
= 'thread:%s;name:%s;' % (self
.encodeThreadID(th_id
), cur_thread
.getName())
157 for rinfo
in self
.registerset
:
160 value
= cur_thread
.getRegisterValueByName(name
)
161 value_endian_correct_str
= self
.encodeRegisterData(value
, bytesize
=(rinfo
['bitsize']/8))
162 retval
+= format
% (pos
, value_endian_correct_str
)
166 def getThreadStopInfo(self
, th_id
):
167 if th_id
not in self
.threads
:
168 logging
.critical("0x%x thread id is not found in this task")
170 return 'T02' + self
.getRegisterCombinedDataForThread(th_id
) + 'threads:' + self
.getThreadsInfo()+';'
172 def getRegisterInfo(self
, regnum
):
173 #something similar to
174 #"name:x1;bitsize:64;offset:8;encoding:uint;format:hex;gcc:1;dwarf:1;set:General Purpose Registers;"
175 if regnum
> len(self
.registerset
):
176 logging
.debug("No register_info for number %d." % regnum
)
179 rinfo
= self
.registerset
[regnum
]
181 for i
in rinfo
.keys():
182 i_val
= str(rinfo
[i
])
184 i_val
= 'General Purpose Registers'
185 retval
+= '%s:%s;' % (str(i
), i_val
)
189 def getProcessInfo(self
):
191 #pid:d22c;parent-pid:d34d;real-uid:ecf;real-gid:b;effective-uid:ecf;effective-gid:b;cputype:1000007;cpusubtype:3;
192 #ostype:macosx;vendor:apple;endian:little;ptrsize:8;
193 pinfo
= {'effective-uid': 'ecf', 'effective-gid': 'b', 'endian': 'little', 'vendor': 'apple'}
194 pinfo
['pid'] = "%x" % (GetProcPIDForTask(self
.task
))
195 pinfo
['parent-pid'] = "%x" % (unsigned(self
.proc
.p_ppid
))
196 pinfo
['ptrsize'] = str(self
.ptrsize
)
197 pinfo
['ostype'] = 'macosx'
198 pinfo
['cputype'] = "%x" % self
.cputype
199 pinfo
['cpusubtype'] = "%x" % self
.cpusubtype
200 pinfo
['real-uid'] = "%x" % (unsigned(self
.proc
.p_ruid
))
201 pinfo
['real-gid'] = "%x" % (unsigned(self
.proc
.p_rgid
))
202 if str(kern
.arch
).find('arm') >= 0:
203 pinfo
['ostype'] = 'ios'
204 for i
in pinfo
.keys():
205 i_val
= str(pinfo
[i
])
206 retval
+= '%s:%s;' % (str(i
), i_val
)
209 def readMemory(self
, address
, size
):
210 data
= GetUserDataAsString(self
.task
, address
, size
)
212 logging
.error("Failed to read memory task:{: <#018x} {: <#018x} {:d}".format(self
.task
, address
, size
))
213 return self
.encodeByteString(data
)
215 def getSharedLibInfoAddress(self
):
216 return unsigned(self
.task
.all_image_info_addr
)