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
14 def GetRegisterSetForCPU(cputype
, subtype
):
15 if cputype
== CPU_TYPE_ARM64
:
16 retval
= Armv8_RegisterSet
17 elif cputype
== CPU_TYPE_ARM
:
18 retval
= Armv7_RegisterSet
19 elif cputype
== CPU_TYPE_I386
:
20 retval
= I386_RegisterSet
21 elif cputype
== CPU_TYPE_X86_64
:
22 retval
= X86_64RegisterSet
24 """ crash if unknown cputype """
26 return retval
.register_info
['registers']
29 class UserThreadObject(object):
30 """representation of userspace thread"""
31 def __init__(self
, thr_obj
, cputype
, cpusubtype
, is_kern_64bit
):
32 super(UserThreadObject
, self
).__init
__()
34 self
.registerset
= GetRegisterSetForCPU(cputype
, cpusubtype
)
35 self
.thread_id
= unsigned(self
.thread
.thread_id
)
36 self
.is64Bit
= bool(cputype
& 0x01000000)
39 if cputype
== CPU_TYPE_X86_64
:
40 self
.reg_type
= "x86_64"
41 self
.saved_state
= Cast(self
.thread
.machine
.iss
, 'x86_saved_state_t *').uss
.ss_64
42 if cputype
== CPU_TYPE_ARM64
:
43 self
.reg_type
= "arm64"
44 self
.saved_state
= self
.thread
.machine
.upcb
.uss
.ss_64
46 if cputype
== CPU_TYPE_I386
:
47 self
.reg_type
= "i386"
48 self
.saved_state
= Cast(self
.thread
.machine
.iss
, 'x86_saved_state_t *').uss
.ss_32
49 if cputype
== CPU_TYPE_ARM
:
52 self
.saved_state
= self
.thread
.machine
.PcbData
54 self
.saved_state
= self
.thread
.machine
.contextData
.ss
.uss
.ss_32
56 logging
.debug("created thread id 0x%x of type %s, is_kern_64bit 0x%x cputype 0x%x"
57 % (self
.thread_id
, self
.reg_type
, is_kern_64bit
, cputype
))
59 def getRegisterValueByName(self
, name
):
60 if self
.reg_type
== 'arm64':
61 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'):
62 return unsigned(getattr(self
.saved_state
, 'x')[int(name
.strip('x'))])
64 return unsigned(getattr(self
.saved_state
, name
))
66 if self
.reg_type
== "x86_64":
67 if name
in ('rip', 'rflags', 'cs', 'rsp', 'cpu'):
68 return unsigned(getattr(self
.saved_state
.isf
, name
))
69 return unsigned(getattr(self
.saved_state
, name
))
71 if self
.reg_type
== "arm":
72 if name
in ('r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10', 'r11', 'r12'):
73 retval
= unsigned(getattr(self
.saved_state
, 'r')[int(name
.strip('r'))])
75 retval
= unsigned(getattr(self
.saved_state
, name
))
81 return str(self
.thread_id
)
83 def getRegisterData(self
, reg_num
):
84 """ returns None if there is error """
85 if reg_num
< 0 or reg_num
>= len(self
.registerset
):
86 logging
.warning("regnum %d is not defined for thread_id 0x%x" % (reg_num
, self
.thread_id
))
88 return self
.getRegisterValueByName(self
.registerset
[reg_num
]['name'])
91 class UserProcess(target
.Process
):
92 """ Represent a user process and thread states """
93 def __init__(self
, task
):
95 self
.proc
= Cast(task
.bsd_info
, 'proc_t')
96 dataregisters64bit
= False
99 if task
.t_flags
& 0x1:
101 if task
.t_flags
& 0x2:
102 dataregisters64bit
= True
104 is_kern_64bit
= kern
.arch
in ['x86_64', 'x86_64h', 'arm64'
107 self
.cputype
= unsigned(self
.proc
.p_cputype
)
108 self
.cpusubtype
= unsigned(self
.proc
.p_cpusubtype
)
110 super(UserProcess
, self
).__init
__(self
.cputype
, self
.cpusubtype
, ptrsize
)
112 self
.hinfo
['ostype'] = 'macosx'
113 if self
.cputype
!= CPU_TYPE_X86_64
and self
.cputype
!= CPU_TYPE_I386
:
114 self
.hinfo
['ostype'] = 'ios'
116 self
.registerset
= GetRegisterSetForCPU(self
.cputype
, self
.cpusubtype
)
117 logging
.debug("process %s is64bit: %d ptrsize: %d cputype: %d cpusubtype:%d",
118 hex(self
.proc
), int(dataregisters64bit
), ptrsize
,
119 self
.cputype
, self
.cpusubtype
122 self
.threads_ids_list
= []
123 logging
.debug("iterating over threads in process")
124 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
125 self
.threads
[unsigned(thval
.thread_id
)] = UserThreadObject(thval
, self
.cputype
, self
.cpusubtype
, is_kern_64bit
)
126 self
.threads_ids_list
.append(unsigned(thval
.thread_id
))
128 def getRegisterDataForThread(self
, th_id
, reg_num
):
129 if th_id
not in self
.threads
:
130 logging
.critical("0x%x thread id is not found in this task")
132 if reg_num
< 0 or reg_num
>= len(self
.registerset
):
133 logging
.warning("regnum %d is not defined for thread_id 0x%x" % (reg_num
, th_id
))
135 value
= self
.threads
[th_id
].getRegisterData(reg_num
)
136 return self
.encodeRegisterData(value
, bytesize
=self
.registerset
[reg_num
]['bitsize']/8)
138 def getRegisterCombinedDataForThread(self
, th_id
):
139 if th_id
not in self
.threads
:
140 logging
.critical("0x%x thread id is not found in this task" % th_id
)
142 cur_thread
= self
.threads
[th_id
]
143 retval
= 'thread:%s;name:%s;' % (self
.encodeThreadID(th_id
), cur_thread
.getName())
145 for rinfo
in self
.registerset
:
148 value
= cur_thread
.getRegisterValueByName(name
)
149 value_endian_correct_str
= self
.encodeRegisterData(value
, bytesize
=(rinfo
['bitsize']/8))
150 retval
+= format
% (pos
, value_endian_correct_str
)
154 def getThreadStopInfo(self
, th_id
):
155 if th_id
not in self
.threads
:
156 logging
.critical("0x%x thread id is not found in this task")
158 return 'T02' + self
.getRegisterCombinedDataForThread(th_id
) + 'threads:' + self
.getThreadsInfo()+';'
160 def getRegisterInfo(self
, regnum
):
161 #something similar to
162 #"name:x1;bitsize:64;offset:8;encoding:uint;format:hex;gcc:1;dwarf:1;set:General Purpose Registers;"
163 if regnum
> len(self
.registerset
):
164 logging
.debug("No register_info for number %d." % regnum
)
167 rinfo
= self
.registerset
[regnum
]
169 for i
in rinfo
.keys():
170 i_val
= str(rinfo
[i
])
172 i_val
= 'General Purpose Registers'
173 retval
+= '%s:%s;' % (str(i
), i_val
)
177 def getProcessInfo(self
):
179 #pid:d22c;parent-pid:d34d;real-uid:ecf;real-gid:b;effective-uid:ecf;effective-gid:b;cputype:1000007;cpusubtype:3;
180 #ostype:macosx;vendor:apple;endian:little;ptrsize:8;
181 pinfo
= {'effective-uid': 'ecf', 'effective-gid': 'b', 'endian': 'little', 'vendor': 'apple'}
182 pinfo
['pid'] = "%x" % (GetProcPIDForTask(self
.task
))
183 pinfo
['parent-pid'] = "%x" % (unsigned(self
.proc
.p_ppid
))
184 pinfo
['ptrsize'] = str(self
.ptrsize
)
185 pinfo
['ostype'] = 'macosx'
186 pinfo
['cputype'] = "%x" % self
.cputype
187 pinfo
['cpusubtype'] = "%x" % self
.cpusubtype
188 pinfo
['real-uid'] = "%x" % (unsigned(self
.proc
.p_ruid
))
189 pinfo
['real-gid'] = "%x" % (unsigned(self
.proc
.p_rgid
))
190 if str(kern
.arch
).find('arm') >= 0:
191 pinfo
['ostype'] = 'ios'
192 for i
in pinfo
.keys():
193 i_val
= str(pinfo
[i
])
194 retval
+= '%s:%s;' % (str(i
), i_val
)
197 def readMemory(self
, address
, size
):
198 data
= GetUserDataAsString(self
.task
, address
, size
)
200 logging
.error("Failed to read memory task:{: <#018x} {: <#018x} {:d}".format(self
.task
, address
, size
))
201 return self
.encodeByteString(data
)
203 def getSharedLibInfoAddress(self
):
204 return unsigned(self
.task
.all_image_info_addr
)