6 from core
.operating_system
import Armv8_RegisterSet
, Armv7_RegisterSet
, I386_RegisterSet
, X86_64RegisterSet
8 """ these defines should come from an authoritative header file """
9 CPU_TYPE_I386
= 0x00000007
10 CPU_TYPE_X86_64
= 0x01000007
11 CPU_TYPE_ARM
= 0x0000000c
12 CPU_TYPE_ARM64
= 0x0100000c
15 CPU_SUBTYPE_X86_64_ALL
= 3
16 CPU_SUBTYPE_X86_64_H
= 8
17 CPU_SUBTYPE_ARMV8
= 13
18 CPU_SUBTYPE_ARM_V7
= 9
19 CPU_SUBTYPE_ARM_V7S
= 11
20 CPU_SUBTYPE_ARM_V7K
= 12
23 def GetRegisterSetForCPU(cputype
, subtype
):
24 if cputype
== CPU_TYPE_ARM64
:
25 retval
= Armv8_RegisterSet
26 elif cputype
== CPU_TYPE_ARM
:
27 retval
= Armv7_RegisterSet
28 elif cputype
== CPU_TYPE_I386
:
29 retval
= I386_RegisterSet
30 elif cputype
== CPU_TYPE_X86_64
:
31 retval
= X86_64RegisterSet
33 """ crash if unknown cputype """
35 return retval
.register_info
['registers']
38 class UserThreadObject(object):
39 """representation of userspace thread"""
40 def __init__(self
, thr_obj
, cputype
, cpusubtype
, kern_cputype
):
41 super(UserThreadObject
, self
).__init
__()
43 self
.registerset
= GetRegisterSetForCPU(cputype
, cpusubtype
)
44 self
.thread_id
= unsigned(self
.thread
.thread_id
)
45 self
.is64Bit
= bool(cputype
& 0x01000000)
46 isKern64Bit
= bool(kern_cputype
& 0x01000000)
49 if cputype
== CPU_TYPE_X86_64
:
50 self
.reg_type
= "x86_64"
51 self
.saved_state
= Cast(self
.thread
.machine
.iss
, 'x86_saved_state_t *').uss
.ss_64
52 if cputype
== CPU_TYPE_ARM64
:
53 self
.reg_type
= "arm64"
54 self
.saved_state
= self
.thread
.machine
.upcb
.uss
.ss_64
56 if cputype
== CPU_TYPE_I386
:
57 self
.reg_type
= "i386"
58 self
.saved_state
= Cast(self
.thread
.machine
.iss
, 'x86_saved_state_t *').uss
.ss_32
59 if cputype
== CPU_TYPE_ARM
:
62 self
.saved_state
= self
.thread
.machine
.PcbData
64 self
.saved_state
= self
.thread
.machine
.contextData
.ss
.uss
.ss_32
65 logging
.debug("created thread id 0x%x of type %s, kern_cputype 0x%x cputype 0x%x"
66 % (self
.thread_id
, self
.reg_type
, kern_cputype
, cputype
))
68 def getRegisterValueByName(self
, name
):
69 if self
.reg_type
== 'arm64':
70 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'):
71 return unsigned(getattr(self
.saved_state
, 'x')[int(name
.strip('x'))])
73 return unsigned(getattr(self
.saved_state
, name
))
75 if self
.reg_type
== "x86_64":
76 if name
in ('rip', 'rflags', 'cs', 'rsp', 'cpu'):
77 return unsigned(getattr(self
.saved_state
.isf
, name
))
78 return unsigned(getattr(self
.saved_state
, name
))
80 if self
.reg_type
== "arm":
81 if name
in ('r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10', 'r11', 'r12'):
82 retval
= unsigned(getattr(self
.saved_state
, 'r')[int(name
.strip('r'))])
84 retval
= unsigned(getattr(self
.saved_state
, name
))
90 return str(self
.thread_id
)
92 def getRegisterData(self
, reg_num
):
93 """ returns None if there is error """
94 if reg_num
< 0 or reg_num
>= len(self
.registerset
):
95 logging
.warning("regnum %d is not defined for thread_id 0x%x" % (reg_num
, self
.thread_id
))
97 return self
.getRegisterValueByName(self
.registerset
[reg_num
]['name'])
100 class UserProcess(target
.Process
):
101 """ Represent a user process and thread states """
102 def __init__(self
, task
):
104 self
.proc
= Cast(task
.bsd_info
, 'proc_t')
105 dataregisters64bit
= False
108 if task
.t_flags
& 0x1:
110 if task
.t_flags
& 0x2:
111 dataregisters64bit
= 8
113 cputype
= CPU_TYPE_X86_64
114 cpusubtype
= CPU_SUBTYPE_X86_64_ALL
117 """ these computations should come out of the macho header i think """
118 """ where does kern.arch come from? what's kern.arch == armv8?? """
119 if kern
.arch
in ('arm'):
120 cputype
= CPU_TYPE_ARM
121 cpusubtype
= CPU_SUBTYPE_ARM_V7
122 elif kern
.arch
in ('armv8', 'arm64'):
123 cputype
= CPU_TYPE_ARM64
124 cpusubtype
= CPU_SUBTYPE_ARMV8
126 super(UserProcess
, self
).__init
__(cputype
, cpusubtype
, ptrsize
)
128 self
.hinfo
['ostype'] = 'macosx'
129 if cputype
!= CPU_TYPE_X86_64
:
130 self
.hinfo
['ostype'] = 'ios'
132 self
.cputype
= unsigned(self
.proc
.p_cputype
)
133 self
.cpusubtype
= unsigned(self
.proc
.p_cpusubtype
)
134 self
.registerset
= GetRegisterSetForCPU(cputype
, cpusubtype
)
135 logging
.debug("process %s is64bit: %d ptrsize: %d cputype: %d cpusubtype:%d",
136 hex(self
.proc
), int(dataregisters64bit
), ptrsize
,
137 self
.cputype
, self
.cpusubtype
140 self
.threads_ids_list
= []
141 logging
.debug("iterating over threads in process")
142 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
143 self
.threads
[unsigned(thval
.thread_id
)] = UserThreadObject(thval
, self
.cputype
, self
.cpusubtype
, cputype
)
144 self
.threads_ids_list
.append(unsigned(thval
.thread_id
))
146 def getRegisterDataForThread(self
, th_id
, reg_num
):
147 if th_id
not in self
.threads
:
148 logging
.critical("0x%x thread id is not found in this task")
150 if reg_num
< 0 or reg_num
>= len(self
.registerset
):
151 logging
.warning("regnum %d is not defined for thread_id 0x%x" % (reg_num
, th_id
))
153 value
= self
.threads
[th_id
].getRegisterData(reg_num
)
154 return self
.encodeRegisterData(value
, bytesize
=self
.registerset
[reg_num
]['bitsize']/8)
156 def getRegisterCombinedDataForThread(self
, th_id
):
157 if th_id
not in self
.threads
:
158 logging
.critical("0x%x thread id is not found in this task" % th_id
)
160 cur_thread
= self
.threads
[th_id
]
161 retval
= 'thread:%s;name:%s;' % (self
.encodeThreadID(th_id
), cur_thread
.getName())
163 for rinfo
in self
.registerset
:
166 value
= cur_thread
.getRegisterValueByName(name
)
167 value_endian_correct_str
= self
.encodeRegisterData(value
, bytesize
=(rinfo
['bitsize']/8))
168 retval
+= format
% (pos
, value_endian_correct_str
)
172 def getThreadStopInfo(self
, th_id
):
173 if th_id
not in self
.threads
:
174 logging
.critical("0x%x thread id is not found in this task")
176 return 'T02' + self
.getRegisterCombinedDataForThread(th_id
) + 'threads:' + self
.getThreadsInfo()+';'
178 def getRegisterInfo(self
, regnum
):
179 #something similar to
180 #"name:x1;bitsize:64;offset:8;encoding:uint;format:hex;gcc:1;dwarf:1;set:General Purpose Registers;"
181 if regnum
> len(self
.registerset
):
182 logging
.debug("No register_info for number %d." % regnum
)
185 rinfo
= self
.registerset
[regnum
]
187 for i
in rinfo
.keys():
188 i_val
= str(rinfo
[i
])
190 i_val
= 'General Purpose Registers'
191 retval
+= '%s:%s;' % (str(i
), i_val
)
195 def getProcessInfo(self
):
197 #pid:d22c;parent-pid:d34d;real-uid:ecf;real-gid:b;effective-uid:ecf;effective-gid:b;cputype:1000007;cpusubtype:3;
198 #ostype:macosx;vendor:apple;endian:little;ptrsize:8;
199 pinfo
= {'effective-uid': 'ecf', 'effective-gid': 'b', 'endian': 'little', 'vendor': 'apple'}
200 pinfo
['pid'] = "%x" % (GetProcPIDForTask(self
.task
))
201 pinfo
['parent-pid'] = "%x" % (unsigned(self
.proc
.p_ppid
))
202 pinfo
['ptrsize'] = str(self
.ptrsize
)
203 pinfo
['ostype'] = 'macosx'
204 pinfo
['cputype'] = "%x" % self
.cputype
205 pinfo
['cpusubtype'] = "%x" % self
.cpusubtype
206 pinfo
['real-uid'] = "%x" % (unsigned(self
.proc
.p_ruid
))
207 pinfo
['real-gid'] = "%x" % (unsigned(self
.proc
.p_rgid
))
208 if str(kern
.arch
).find('arm') >= 0:
209 pinfo
['ostype'] = 'ios'
210 for i
in pinfo
.keys():
211 i_val
= str(pinfo
[i
])
212 retval
+= '%s:%s;' % (str(i
), i_val
)
215 def readMemory(self
, address
, size
):
216 data
= GetUserDataAsString(self
.task
, address
, size
)
218 logging
.error("Failed to read memory task:{: <#018x} {: <#018x} {:d}".format(self
.task
, address
, size
))
219 return self
.encodeByteString(data
)
221 def getSharedLibInfoAddress(self
):
222 return unsigned(self
.task
.all_image_info_addr
)