]> git.saurik.com Git - apple/xnu.git/blame - tools/lldbmacros/core/kernelcore.py
xnu-7195.101.1.tar.gz
[apple/xnu.git] / tools / lldbmacros / core / kernelcore.py
CommitLineData
39236c6e
A
1
2""" Please make sure you read the README COMPLETELY BEFORE reading anything below.
3 It is very critical that you read coding guidelines in Section E in README file.
4"""
5
6from cvalue import *
7from lazytarget import *
8from configuration import *
d9a64523 9from utils import *
39236c6e
A
10import caching
11import lldb
12
13def IterateTAILQ_HEAD(headval, element_name):
14 """ iterate over a TAILQ_HEAD in kernel. refer to bsd/sys/queue.h
15 params:
16 headval - value : value object representing the head of the list
17 element_name- str : string name of the field which holds the list links.
18 returns:
19 A generator does not return. It is used for iterating.
20 value : an object that is of type as headval->tqh_first. Always a pointer object
21 example usage:
22 list_head = kern.GetGlobalVariable('mountlist')
23 for entryobj in IterateTAILQ_HEAD(list_head, 'mnt_list'):
24 print GetEntrySummary(entryobj)
25 """
26 iter_val = headval.tqh_first
27 while unsigned(iter_val) != 0 :
28 yield iter_val
29 iter_val = iter_val.__getattr__(element_name).tqe_next
30 #end of yield loop
31
32def IterateLinkedList(element, field_name):
33 """ iterate over a linked list.
34 This is equivalent to elt = element; while(elt) { do_work(elt); elt = elt-><field_name>; }
35 params:
36 element - value : value object representing element in the list.
37 field_name - str : name of field that holds pointer to next element
38 returns: Nothing. This is used as iterable
39 example usage:
40 first_zone = kern.GetGlobalVariable('first_zone')
41 for zone in IterateLinkedList(first_zone, 'next_zone'):
42 print GetZoneSummary(zone)
43 """
44 elt = element
45 while unsigned(elt) != 0:
46 yield elt
47 elt = elt.__getattr__(field_name)
48 #end of while loop
49
5ba3f43e 50def IterateListEntry(element, element_type, field_name, list_prefix=''):
39236c6e
A
51 """ iterate over a list as defined with LIST_HEAD in bsd/sys/queue.h
52 params:
53 element - value : Value object for lh_first
54 element_type - str : Type of the next element
55 field_name - str : Name of the field in next element's structure
cc8bc92a 56 list_prefix - str : use 's' here to iterate SLIST_HEAD instead
39236c6e
A
57 returns:
58 A generator does not return. It is used for iterating
59 value : an object thats of type (element_type) head->le_next. Always a pointer object
60 example usage:
61 headp = kern.globals.initproc.p_children
62 for pp in IterateListEntry(headp, 'struct proc *', 'p_sibling'):
63 print GetProcInfo(pp)
64 """
5ba3f43e 65 elt = element.__getattr__(list_prefix + 'lh_first')
39236c6e
A
66 if type(element_type) == str:
67 element_type = gettype(element_type)
68 while unsigned(elt) != 0:
69 yield elt
5ba3f43e 70 next_el = elt.__getattr__(field_name).__getattr__(list_prefix + 'le_next')
39236c6e
A
71 elt = cast(next_el, element_type)
72
3e170ce0
A
73def IterateLinkageChain(queue_head, element_type, field_name, field_ofst=0):
74 """ Iterate over a Linkage Chain queue in kernel of type queue_head_t. (osfmk/kern/queue.h method 1)
75 This is equivalent to the qe_foreach_element() macro
76 params:
77 queue_head - value : Value object for queue_head.
78 element_type - lldb.SBType : pointer type of the element which contains the queue_chain_t. Typically its structs like thread, task etc..
79 - str : OR a string describing the type. ex. 'task *'
80 field_name - str : Name of the field (in element) which holds a queue_chain_t
81 field_ofst - int : offset from the 'field_name' (in element) which holds a queue_chain_t
82 This is mostly useful if a particular element contains an array of queue_chain_t
83 returns:
84 A generator does not return. It is used for iterating.
85 value : An object thats of type (element_type). Always a pointer object
86 example usage:
87 coalq = kern.GetGlobalVariable('coalitions_q')
88 for coal in IterateLinkageChain(coalq, 'struct coalition *', 'coalitions'):
89 print GetCoalitionInfo(coal)
90 """
91 global kern
92 if type(element_type) == str:
93 element_type = gettype(element_type)
94
95 if unsigned(queue_head) == 0:
96 return
97
98 if element_type.IsPointerType():
99 elem_ofst = getfieldoffset(element_type.GetPointeeType(), field_name) + field_ofst
100 else:
101 elem_ofst = getfieldoffset(element_type, field_name) + field_ofst
102
103 link = queue_head.next
104 while (unsigned(link) != unsigned(queue_head)):
105 addr = unsigned(link) - elem_ofst;
106 # I can't use the GetValueFromAddress function of the kernel class
107 # because I have no instance of that class!
108 obj = value(link.GetSBValue().CreateValueFromExpression(None,'(void *)'+str(addr)))
109 obj = cast(obj, element_type)
110 yield obj
111 link = link.next
112
ea3f0419
A
113def IterateCircleQueue(queue_head, element_ptr_type, element_field_name):
114 """ iterate over a circle queue in kernel of type circle_queue_head_t. refer to osfmk/kern/circle_queue.h
115 params:
116 queue_head - lldb.SBValue : Value object for queue_head.
117 element_type - lldb.SBType : a pointer type of the element 'next' points to. Typically its structs like thread, task etc..
118 element_field_name - str : name of the field in target struct.
119 returns:
120 A generator does not return. It is used for iterating.
121 SBValue : an object thats of type (element_type) queue_head->next. Always a pointer object
122 """
123 head = queue_head.head.GetSBValue()
124 queue_head_addr = 0x0
125 if head.TypeIsPointerType():
126 queue_head_addr = head.GetValueAsUnsigned()
127 else:
128 queue_head_addr = head.GetAddress().GetLoadAddress(osplugin_target_obj)
129 cur_elt = head
130 while True:
131 if not cur_elt.IsValid() or cur_elt.GetValueAsUnsigned() == 0:
132 break
133 yield containerof(value(cur_elt), element_ptr_type, element_field_name)
134 cur_elt = cur_elt.GetChildMemberWithName('next')
135 if cur_elt.GetValueAsUnsigned() == queue_head_addr:
136 break
3e170ce0 137
39037602 138def IterateQueue(queue_head, element_ptr_type, element_field_name, backwards=False, unpack_ptr_fn=None):
3e170ce0 139 """ Iterate over an Element Chain queue in kernel of type queue_head_t. (osfmk/kern/queue.h method 2)
39236c6e
A
140 params:
141 queue_head - value : Value object for queue_head.
3e170ce0 142 element_ptr_type - lldb.SBType : a pointer type of the element 'next' points to. Typically its structs like thread, task etc..
39236c6e
A
143 - str : OR a string describing the type. ex. 'task *'
144 element_field_name - str : name of the field in target struct.
3e170ce0 145 backwards - backwards : traverse the queue backwards
39037602 146 unpack_ptr_fn - function : a function ptr of signature def unpack_ptr(long v) which returns long.
39236c6e
A
147 returns:
148 A generator does not return. It is used for iterating.
149 value : an object thats of type (element_type) queue_head->next. Always a pointer object
fe8ab488
A
150 example usage:
151 for page_meta in IterateQueue(kern.globals.first_zone.pages.all_free, 'struct zone_page_metadata *', 'pages'):
152 print page_meta
39236c6e
A
153 """
154 if type(element_ptr_type) == str :
155 element_ptr_type = gettype(element_ptr_type)
156
157 queue_head = queue_head.GetSBValue()
158 queue_head_addr = 0x0
159 if queue_head.TypeIsPointerType():
160 queue_head_addr = queue_head.GetValueAsUnsigned()
161 else:
162 queue_head_addr = queue_head.GetAddress().GetLoadAddress(LazyTarget.GetTarget())
39037602
A
163
164 def unpack_ptr_and_recast(v):
165 if unpack_ptr_fn is None:
166 return v
167 v_unpacked = unpack_ptr_fn(v.GetValueAsUnsigned())
168 obj = v.CreateValueFromExpression(None,'(void *)'+str(v_unpacked))
169 obj.Cast(element_ptr_type)
170 return obj
171
3e170ce0 172 if backwards:
39037602 173 cur_elt = unpack_ptr_and_recast(queue_head.GetChildMemberWithName('prev'))
3e170ce0 174 else:
39037602 175 cur_elt = unpack_ptr_and_recast(queue_head.GetChildMemberWithName('next'))
3e170ce0 176
39236c6e
A
177 while True:
178
179 if not cur_elt.IsValid() or cur_elt.GetValueAsUnsigned() == 0 or cur_elt.GetValueAsUnsigned() == queue_head_addr:
180 break
181 elt = cur_elt.Cast(element_ptr_type)
182 yield value(elt)
3e170ce0 183 if backwards:
39037602 184 cur_elt = unpack_ptr_and_recast(elt.GetChildMemberWithName(element_field_name).GetChildMemberWithName('prev'))
3e170ce0 185 else:
39037602
A
186 cur_elt = unpack_ptr_and_recast(elt.GetChildMemberWithName(element_field_name).GetChildMemberWithName('next'))
187
39236c6e 188
cc8bc92a
A
189def IterateRBTreeEntry(element, element_type, field_name):
190 """ iterate over a rbtree as defined with RB_HEAD in libkern/tree.h
191 element - value : Value object for rbh_root
192 element_type - str : Type of the link element
193 field_name - str : Name of the field in link element's structure
194 returns:
195 A generator does not return. It is used for iterating
196 value : an object thats of type (element_type) head->sle_next. Always a pointer object
197 """
198 elt = element.__getattr__('rbh_root')
199 if type(element_type) == str:
200 element_type = gettype(element_type)
201
202 # Walk to find min
203 parent = elt
204 while unsigned(elt) != 0:
205 parent = elt
206 elt = cast(elt.__getattr__(field_name).__getattr__('rbe_left'), element_type)
207 elt = parent
208
209 # Now elt is min
210 while unsigned(elt) != 0:
211 yield elt
212 # implementation cribbed from RB_NEXT in libkern/tree.h
213 right = cast(elt.__getattr__(field_name).__getattr__('rbe_right'), element_type)
214 if unsigned(right) != 0:
215 elt = right
216 left = cast(elt.__getattr__(field_name).__getattr__('rbe_left'), element_type)
217 while unsigned(left) != 0:
218 elt = left
219 left = cast(elt.__getattr__(field_name).__getattr__('rbe_left'), element_type)
220 else:
221
222 # avoid using GetValueFromAddress
223 addr = elt.__getattr__(field_name).__getattr__('rbe_parent')&~1
224 parent = value(elt.GetSBValue().CreateValueFromExpression(None,'(void *)'+str(addr)))
225 parent = cast(parent, element_type)
226
227 if unsigned(parent) != 0:
228 left = cast(parent.__getattr__(field_name).__getattr__('rbe_left'), element_type)
229 if (unsigned(parent) != 0) and (unsigned(elt) == unsigned(left)):
230 elt = parent
231 else:
232 if unsigned(parent) != 0:
233 right = cast(parent.__getattr__(field_name).__getattr__('rbe_right'), element_type)
234 while unsigned(parent) != 0 and (unsigned(elt) == unsigned(right)):
235 elt = parent
236
237 # avoid using GetValueFromAddress
238 addr = elt.__getattr__(field_name).__getattr__('rbe_parent')&~1
239 parent = value(elt.GetSBValue().CreateValueFromExpression(None,'(void *)'+str(addr)))
240 parent = cast(parent, element_type)
241
242 right = cast(parent.__getattr__(field_name).__getattr__('rbe_right'), element_type)
243
244 # avoid using GetValueFromAddress
245 addr = elt.__getattr__(field_name).__getattr__('rbe_parent')&~1
246 elt = value(elt.GetSBValue().CreateValueFromExpression(None,'(void *)'+str(addr)))
247 elt = cast(elt, element_type)
248
249
f427ee49 250def IterateSchedPriorityQueue(root, element_type, field_name):
d9a64523
A
251 """ iterate over a priority queue as defined with struct priority_queue from osfmk/kern/priority_queue.h
252 root - value : Value object for the priority queue
253 element_type - str : Type of the link element
254 field_name - str : Name of the field in link element's structure
255 returns:
256 A generator does not return. It is used for iterating
257 value : an object thats of type (element_type). Always a pointer object
258 """
259 def _make_pqe(addr):
f427ee49 260 return value(root.GetSBValue().CreateValueFromExpression(None,'(struct priority_queue_entry_sched *)'+str(addr)))
d9a64523 261
f427ee49 262 queue = [unsigned(root.pq_root)]
d9a64523
A
263
264 while len(queue):
265 elt = _make_pqe(queue.pop())
266
267 while elt:
268 yield containerof(elt, element_type, field_name)
269 addr = unsigned(elt.child)
270 if addr: queue.append(addr)
271 elt = elt.next
272
f427ee49
A
273def SchedPriorityStableQueueRootPri(root, element_type, field_name):
274 """ Return the root level priority of a priority queue as defined with struct priority_queue from osfmk/kern/priority_queue.h
275 root - value : Value object for the priority queue
276 element_type - str : Type of the link element
277 field_name - str : Name of the field in link element's structure
278 returns:
279 The sched pri of the root element.
280 """
281 def _make_pqe(addr):
282 return value(root.GetSBValue().CreateValueFromExpression(None,'(struct priority_queue_entry_stable *)'+str(addr)))
283
284 elt = _make_pqe(unsigned(root.pq_root))
285 return (elt.key >> 8);
286
cb323159
A
287def IterateMPSCQueue(root, element_type, field_name):
288 """ iterate over an MPSC queue as defined with struct mpsc_queue_head from osfmk/kern/mpsc_queue.h
289 root - value : Value object for the mpsc queue
290 element_type - str : Type of the link element
291 field_name - str : Name of the field in link element's structure
292 returns:
293 A generator does not return. It is used for iterating
294 value : an object thats of type (element_type). Always a pointer object
295 """
296 elt = root.mpqh_head.mpqc_next
297 while unsigned(elt):
298 yield containerof(elt, element_type, field_name)
299 elt = elt.mpqc_next
d9a64523 300
39236c6e
A
301class KernelTarget(object):
302 """ A common kernel object that provides access to kernel objects and information.
303 The class holds global lists for task, terminated_tasks, procs, zones, zombroc etc.
304 It also provides a way to symbolicate an address or create a value from an address.
305 """
306 def __init__(self, debugger):
307 """ Initialize the kernel debugging environment.
308 Target properties like architecture and connectedness are lazy-evaluted.
309 """
310 self._debugger = debugger # This holds an lldb.SBDebugger object for debugger state
311 self._threads_list = []
312 self._tasks_list = []
fe8ab488 313 self._coalitions_list = []
5ba3f43e 314 self._thread_groups = []
39236c6e
A
315 self._allproc = []
316 self._terminated_tasks_list = []
c3c9b80d 317 self._terminated_threads_list = []
39236c6e
A
318 self._zones_list = []
319 self._zombproc_list = []
320 self._kernel_types_cache = {} #this will cache the Type objects as and when requested.
321 self._version = None
322 self._arch = None
323 self._ptrsize = None # pointer size of kernel, not userspace
324 self.symbolicator = None
325 class _GlobalVariableFind(object):
326 def __init__(self, kern):
327 self._xnu_kernobj_12obscure12 = kern
328 def __getattr__(self, name):
329 v = self._xnu_kernobj_12obscure12.GetGlobalVariable(name)
330 if not v.GetSBValue().IsValid():
3e170ce0 331 raise ValueError('No such global variable by name: %s '%str(name))
39236c6e
A
332 return v
333 self.globals = _GlobalVariableFind(self)
334 LazyTarget.Initialize(debugger)
335
336 def _GetSymbolicator(self):
337 """ Internal function: To initialize the symbolication from lldb.utils
338 """
339 if not self.symbolicator is None:
340 return self.symbolicator
341
342 from lldb.utils import symbolication
343 symbolicator = symbolication.Symbolicator()
344 symbolicator.target = LazyTarget.GetTarget()
345 self.symbolicator = symbolicator
346 return self.symbolicator
347
348 def Symbolicate(self, addr):
349 """ simple method to get name of function/variable from an address. this is equivalent of gdb 'output /a 0xaddress'
350 params:
351 addr - int : typically hex value like 0xffffff80002c0df0
352 returns:
353 str - '' if no symbol found else the symbol name.
354 Note: this function only finds the first symbol. If you expect multiple symbol conflict please use SymbolicateFromAddress()
355 """
356 ret_str = ''
357 syms = self.SymbolicateFromAddress(addr)
358 if len(syms) > 0:
359 ret_str +=syms[0].GetName()
360 return ret_str
361
362 def SymbolicateFromAddress(self, addr):
363 """ symbolicates any given address based on modules loaded in the target.
364 params:
365 addr - int : typically hex value like 0xffffff80002c0df0
366 returns:
367 [] of SBSymbol: In case we don't find anything than empty array is returned.
368 Note: a type of symbol can be figured out by gettype() function of SBSymbol.
369 example usage:
370 syms = kern.Symbolicate(0xffffff80002c0df0)
371 for s in syms:
372 if s.GetType() == lldb.eSymbolTypeCode:
373 print "Function", s.GetName()
374 if s.GetType() == lldb.eSymbolTypeData:
375 print "Variable", s.GetName()
376 """
377 if type(int(1)) != type(addr):
378 if str(addr).strip().find("0x") == 0 :
379 addr = int(addr, 16)
380 else:
381 addr = int(addr)
cb323159 382 addr = self.StripKernelPAC(addr)
39236c6e
A
383 ret_array = []
384 symbolicator = self._GetSymbolicator()
385 syms = symbolicator.symbolicate(addr)
386 if not syms:
387 return ret_array
388 for s in syms:
389 ret_array.append(s.get_symbol_context().symbol)
390 return ret_array
391
392 def IsDebuggerConnected(self):
393 proc_state = LazyTarget.GetProcess().state
394 if proc_state == lldb.eStateInvalid : return False
395 if proc_state in [lldb.eStateStopped, lldb.eStateSuspended] : return True
396
397 def GetGlobalVariable(self, name):
398 """ Get the value object representation for a kernel global variable
399 params:
400 name : str - name of the variable. ex. version
401 returns: value - python object representing global variable.
402 raises : Exception in case the variable is not found.
403 """
3e170ce0
A
404 self._globals_cache_dict = caching.GetDynamicCacheData("kern._globals_cache_dict", {})
405 if name not in self._globals_cache_dict:
406 self._globals_cache_dict[name] = value(LazyTarget.GetTarget().FindGlobalVariables(name, 1).GetValueAtIndex(0))
407 return self._globals_cache_dict[name]
39236c6e
A
408
409 def GetLoadAddressForSymbol(self, name):
410 """ Get the load address of a symbol in the kernel.
411 params:
412 name : str - name of the symbol to lookup
413 returns: int - the load address as an integer. Use GetValueFromAddress to cast to a value.
414 raises : LookupError - if the symbol is not found.
415 """
416 name = str(name)
417 target = LazyTarget.GetTarget()
418 syms_arr = target.FindSymbols(name)
419 if syms_arr.IsValid() and len(syms_arr) > 0:
420 symbol = syms_arr[0].GetSymbol()
421 if symbol.IsValid():
422 return int(symbol.GetStartAddress().GetLoadAddress(target))
423
424 raise LookupError("Symbol not found: " + name)
425
426 def GetValueFromAddress(self, addr, type_str = 'void *'):
427 """ convert a address to value
428 params:
429 addr - int : typically hex value like 0xffffff80008dc390
430 type_str - str: type to cast to. Default type will be void *
431 returns:
432 value : a value object which has address as addr and type is type_str
433 """
434 obj = value(self.globals.version.GetSBValue().CreateValueFromExpression(None,'(void *)'+str(addr)))
435 obj = cast(obj, type_str)
436 return obj
437
438 def GetValueAsType(self, v, t):
439 """ Retrieves a global variable 'v' of type 't' wrapped in a vue object.
440 If 'v' is an address, creates a vue object of the appropriate type.
441 If 'v' is a name, looks for the global variable and asserts its type.
442 Throws:
443 NameError - If 'v' cannot be found
444 TypeError - If 'v' is of the wrong type
445 """
446 if islong(v):
447 return self.GetValueFromAddress(v, t)
448 else:
449 var = LazyTarget.GetTarget().FindGlobalVariables(v, 1)[0]
450 if not var:
451 raise NameError("Failed to find global variable '{0}'".format(v))
452 if var.GetTypeName() != t:
453 raise TypeError("{0} must be of type '{1}', not '{2}'".format(v, t, var.GetTypeName()))
454 return value(var)
455
456 def _GetIterator(self, iter_head_name, next_element_name='next', iter_head_type=None):
457 """ returns an iterator for a collection in kernel memory.
458 params:
459 iter_head_name - str : name of queue_head or list head variable.
460 next_element_name - str : name of the element that leads to next element.
461 for ex. in struct zone list 'next_zone' is the linking element.
462 returns:
463 iterable : typically used in conjunction with "for varname in iterable:"
464 """
465 head_element = self.GetGlobalVariable(iter_head_name)
466 return head_element.GetSBValue().linked_list_iter(next_element_name)
467
468 def TruncPage(self, addr):
469 return (addr & ~(unsigned(self.GetGlobalVariable("page_size")) - 1))
470
471 def RoundPage(self, addr):
472 return trunc_page(addr + unsigned(self.GetGlobalVariable("page_size")) - 1)
473
474 def StraddlesPage(self, addr, size):
475 if size > unsigned(self.GetGlobalVariable("page_size")):
476 return True
fe8ab488
A
477 val = ((addr + size) & (unsigned(self.GetGlobalVariable("page_size"))-1))
478 return (val < size and val > 0)
39236c6e 479
cb323159
A
480 def StripUserPAC(self, addr):
481 if self.arch != 'arm64e':
482 return addr
483 T0Sz = self.GetGlobalVariable('gT0Sz')
484 return StripPAC(addr, T0Sz)
485
486 def StripKernelPAC(self, addr):
487 if self.arch != 'arm64e':
488 return addr
489 T1Sz = self.GetGlobalVariable('gT1Sz')
490 return StripPAC(addr, T1Sz)
d9a64523
A
491
492 def PhysToKVARM64(self, addr):
493 ptov_table = self.GetGlobalVariable('ptov_table')
494 for i in range(0, self.GetGlobalVariable('ptov_index')):
495 if (addr >= long(unsigned(ptov_table[i].pa))) and (addr < (long(unsigned(ptov_table[i].pa)) + long(unsigned(ptov_table[i].len)))):
496 return (addr - long(unsigned(ptov_table[i].pa)) + long(unsigned(ptov_table[i].va)))
497 return (addr - unsigned(self.GetGlobalVariable("gPhysBase")) + unsigned(self.GetGlobalVariable("gVirtBase")))
498
39236c6e
A
499 def PhysToKernelVirt(self, addr):
500 if self.arch == 'x86_64':
501 return (addr + unsigned(self.GetGlobalVariable('physmap_base')))
d9a64523
A
502 elif self.arch.startswith('arm64'):
503 return self.PhysToKVARM64(addr)
5ba3f43e 504 elif self.arch.startswith('arm'):
39236c6e
A
505 return (addr - unsigned(self.GetGlobalVariable("gPhysBase")) + unsigned(self.GetGlobalVariable("gVirtBase")))
506 else:
5ba3f43e 507 raise ValueError("PhysToVirt does not support {0}".format(self.arch))
39236c6e 508
3e170ce0
A
509 def GetNanotimeFromAbstime(self, abstime):
510 """ convert absolute time (which is in MATUs) to nano seconds.
511 Since based on architecture the conversion may differ.
512 params:
513 abstime - int absolute time as shown by mach_absolute_time
514 returns:
515 int - nanosecs of time
516 """
517 usec_divisor = caching.GetStaticCacheData("kern.rtc_usec_divisor", None)
518 if not usec_divisor:
519 if self.arch == 'x86_64':
520 usec_divisor = 1000
521 else:
522 rtclockdata_addr = self.GetLoadAddressForSymbol('RTClockData')
523 rtc = self.GetValueFromAddress(rtclockdata_addr, 'struct _rtclock_data_ *')
524 usec_divisor = unsigned(rtc.rtc_usec_divisor)
525 usec_divisor = int(usec_divisor)
526 caching.SaveStaticCacheData('kern.rtc_usec_divisor', usec_divisor)
527 nsecs = (abstime * 1000)/usec_divisor
528 return nsecs
529
39236c6e
A
530 def __getattribute__(self, name):
531 if name == 'zones' :
532 self._zones_list = caching.GetDynamicCacheData("kern._zones_list", [])
533 if len(self._zones_list) > 0: return self._zones_list
39037602
A
534 zone_array = self.GetGlobalVariable('zone_array')
535 for i in range(0, self.GetGlobalVariable('num_zones')):
536 self._zones_list.append(addressof(zone_array[i]))
39236c6e
A
537 caching.SaveDynamicCacheData("kern._zones_list", self._zones_list)
538 return self._zones_list
539
540 if name == 'threads' :
541 self._threads_list = caching.GetDynamicCacheData("kern._threads_list", [])
542 if len(self._threads_list) > 0 : return self._threads_list
543 thread_queue_head = self.GetGlobalVariable('threads')
544 thread_type = LazyTarget.GetTarget().FindFirstType('thread')
545 thread_ptr_type = thread_type.GetPointerType()
546 for th in IterateQueue(thread_queue_head, thread_ptr_type, 'threads'):
547 self._threads_list.append(th)
548 caching.SaveDynamicCacheData("kern._threads_list", self._threads_list)
549 return self._threads_list
550
551 if name == 'tasks' :
552 self._tasks_list = caching.GetDynamicCacheData("kern._tasks_list", [])
553 if len(self._tasks_list) > 0 : return self._tasks_list
554 task_queue_head = self.GetGlobalVariable('tasks')
555 task_type = LazyTarget.GetTarget().FindFirstType('task')
556 task_ptr_type = task_type.GetPointerType()
557 for tsk in IterateQueue(task_queue_head, task_ptr_type, 'tasks'):
558 self._tasks_list.append(tsk)
559 caching.SaveDynamicCacheData("kern._tasks_list", self._tasks_list)
560 return self._tasks_list
561
fe8ab488
A
562 if name == 'coalitions' :
563 self._coalitions_list = caching.GetDynamicCacheData("kern._coalitions_list", [])
564 if len(self._coalitions_list) > 0 : return self._coalitions_list
3e170ce0 565 coalition_queue_head = self.GetGlobalVariable('coalitions_q')
fe8ab488
A
566 coalition_type = LazyTarget.GetTarget().FindFirstType('coalition')
567 coalition_ptr_type = coalition_type.GetPointerType()
3e170ce0
A
568 for coal in IterateLinkageChain(addressof(coalition_queue_head), coalition_ptr_type, 'coalitions'):
569 self._coalitions_list.append(coal)
fe8ab488
A
570 caching.SaveDynamicCacheData("kern._coalitions_list", self._coalitions_list)
571 return self._coalitions_list
572
5ba3f43e
A
573 if name == 'thread_groups' :
574 self._thread_groups_list = caching.GetDynamicCacheData("kern._thread_groups_list", [])
575 if len(self._thread_groups_list) > 0 : return self._thread_groups_list
576 thread_groups_queue_head = self.GetGlobalVariable('tg_queue')
577 thread_group_type = LazyTarget.GetTarget().FindFirstType('thread_group')
578 thread_groups_ptr_type = thread_group_type.GetPointerType()
579 for coal in IterateLinkageChain(addressof(thread_groups_queue_head), thread_groups_ptr_type, 'tg_queue_chain'):
580 self._thread_groups_list.append(coal)
581 caching.SaveDynamicCacheData("kern._thread_groups_list", self._thread_groups_list)
582 return self._thread_groups_list
583
39236c6e
A
584 if name == 'terminated_tasks' :
585 self._terminated_tasks_list = caching.GetDynamicCacheData("kern._terminated_tasks_list", [])
586 if len(self._terminated_tasks_list) > 0 : return self._terminated_tasks_list
587 task_queue_head = self.GetGlobalVariable('terminated_tasks')
588 task_type = LazyTarget.GetTarget().FindFirstType('task')
589 task_ptr_type = task_type.GetPointerType()
590 for tsk in IterateQueue(task_queue_head, task_ptr_type, 'tasks'):
591 self._terminated_tasks_list.append(tsk)
592 caching.SaveDynamicCacheData("kern._terminated_tasks_list", self._terminated_tasks_list)
593 return self._terminated_tasks_list
594
c3c9b80d
A
595 if name == 'terminated_threads' :
596 self._terminated_threads_list = caching.GetDynamicCacheData("kern._terminated_threads_list", [])
597 if len(self._terminated_threads_list) > 0 : return self._terminated_threads_list
598 thread_queue_head = self.GetGlobalVariable('terminated_threads')
599 thread_type = LazyTarget.GetTarget().FindFirstType('thread')
600 thread_ptr_type = thread_type.GetPointerType()
601 for trd in IterateQueue(thread_queue_head, thread_ptr_type, 'threads'):
602 self._terminated_threads_list.append(trd)
603 caching.SaveDynamicCacheData("kern._terminated_threads_list", self._terminated_threads_list)
604 return self._terminated_threads_list
605
39236c6e
A
606 if name == 'procs' :
607 self._allproc = caching.GetDynamicCacheData("kern._allproc", [])
608 if len(self._allproc) > 0 : return self._allproc
609 all_proc_head = self.GetGlobalVariable('allproc')
610 proc_val = cast(all_proc_head.lh_first, 'proc *')
611 while proc_val != 0:
612 self._allproc.append(proc_val)
613 proc_val = cast(proc_val.p_list.le_next, 'proc *')
614 caching.SaveDynamicCacheData("kern._allproc", self._allproc)
615 return self._allproc
616
fe8ab488
A
617 if name == 'interrupt_stats' :
618 self._interrupt_stats_list = caching.GetDynamicCacheData("kern._interrupt_stats_list", [])
619 if len(self._interrupt_stats_list) > 0 : return self._interrupt_stats_list
620 interrupt_stats_head = self.GetGlobalVariable('gInterruptAccountingDataList')
621 interrupt_stats_type = LazyTarget.GetTarget().FindFirstType('IOInterruptAccountingData')
622 interrupt_stats_ptr_type = interrupt_stats_type.GetPointerType()
623 for interrupt_stats_obj in IterateQueue(interrupt_stats_head, interrupt_stats_ptr_type, 'chain'):
624 self._interrupt_stats_list.append(interrupt_stats_obj)
625 caching.SaveDynamicCacheData("kern._interrupt_stats", self._interrupt_stats_list)
626 return self._interrupt_stats_list
627
39236c6e
A
628 if name == 'zombprocs' :
629 self._zombproc_list = caching.GetDynamicCacheData("kern._zombproc_list", [])
630 if len(self._zombproc_list) > 0 : return self._zombproc_list
631 zproc_head = self.GetGlobalVariable('zombproc')
632 proc_val = cast(zproc_head.lh_first, 'proc *')
633 while proc_val != 0:
634 self._zombproc_list.append(proc_val)
635 proc_val = cast(proc_val.p_list.le_next, 'proc *')
636 caching.SaveDynamicCacheData("kern._zombproc_list", self._zombproc_list)
637 return self._zombproc_list
638
639 if name == 'version' :
640 self._version = caching.GetStaticCacheData("kern.version", None)
641 if self._version != None : return self._version
642 self._version = str(self.GetGlobalVariable('version'))
643 caching.SaveStaticCacheData("kern.version", self._version)
644 return self._version
645
646 if name == 'arch' :
647 self._arch = caching.GetStaticCacheData("kern.arch", None)
648 if self._arch != None : return self._arch
649 arch = LazyTarget.GetTarget().triple.split('-')[0]
fe8ab488 650 if arch in ('armv7', 'armv7s', 'armv7k'):
39236c6e
A
651 self._arch = 'arm'
652 else:
653 self._arch = arch
654 caching.SaveStaticCacheData("kern.arch", self._arch)
655 return self._arch
656
657 if name == 'ptrsize' :
658 self._ptrsize = caching.GetStaticCacheData("kern.ptrsize", None)
659 if self._ptrsize != None : return self._ptrsize
660 arch = LazyTarget.GetTarget().triple.split('-')[0]
d9a64523 661 if arch == 'x86_64' or arch.startswith('arm64'):
39236c6e
A
662 self._ptrsize = 8
663 else:
664 self._ptrsize = 4
665 caching.SaveStaticCacheData("kern.ptrsize", self._ptrsize)
666 return self._ptrsize
667
5ba3f43e
A
668 if name == 'VM_MIN_KERNEL_ADDRESS':
669 if self.arch == 'x86_64':
670 return unsigned(0xFFFFFF8000000000)
d9a64523 671 elif self.arch.startswith('arm64'):
5ba3f43e
A
672 return unsigned(0xffffffe000000000)
673 else:
674 return unsigned(0x80000000)
675
676 if name == 'VM_MIN_KERNEL_AND_KEXT_ADDRESS':
677 if self.arch == 'x86_64':
678 return self.VM_MIN_KERNEL_ADDRESS - 0x80000000
679 else:
680 return self.VM_MIN_KERNEL_ADDRESS
681
39236c6e 682 return object.__getattribute__(self, name)