]>
git.saurik.com Git - apple/xnu.git/blob - tools/lldbmacros/core/kernelcore.py
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.
7 from lazytarget
import *
8 from configuration
import *
13 def IterateTAILQ_HEAD(headval
, element_name
):
14 """ iterate over a TAILQ_HEAD in kernel. refer to bsd/sys/queue.h
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.
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
22 list_head = kern.GetGlobalVariable('mountlist')
23 for entryobj in IterateTAILQ_HEAD(list_head, 'mnt_list'):
24 print GetEntrySummary(entryobj)
26 iter_val
= headval
.tqh_first
27 while unsigned(iter_val
) != 0 :
29 iter_val
= iter_val
.__getattr
__(element_name
).tqe_next
32 def 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>; }
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
40 first_zone = kern.GetGlobalVariable('first_zone')
41 for zone in IterateLinkedList(first_zone, 'next_zone'):
42 print GetZoneSummary(zone)
45 while unsigned(elt
) != 0:
47 elt
= elt
.__getattr
__(field_name
)
50 def IterateListEntry(element
, element_type
, field_name
, list_prefix
=''):
51 """ iterate over a list as defined with LIST_HEAD in bsd/sys/queue.h
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
56 list_prefix - str : use 's' here to iterate SLIST_HEAD instead
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
61 headp = kern.globals.initproc.p_children
62 for pp in IterateListEntry(headp, 'struct proc *', 'p_sibling'):
65 elt
= element
.__getattr
__(list_prefix
+ 'lh_first')
66 if type(element_type
) == str:
67 element_type
= gettype(element_type
)
68 while unsigned(elt
) != 0:
70 next_el
= elt
.__getattr
__(field_name
).__getattr
__(list_prefix
+ 'le_next')
71 elt
= cast(next_el
, element_type
)
73 def 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
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
84 A generator does not return. It is used for iterating.
85 value : An object thats of type (element_type). Always a pointer object
87 coalq = kern.GetGlobalVariable('coalitions_q')
88 for coal in IterateLinkageChain(coalq, 'struct coalition *', 'coalitions'):
89 print GetCoalitionInfo(coal)
92 if type(element_type
) == str:
93 element_type
= gettype(element_type
)
95 if unsigned(queue_head
) == 0:
98 if element_type
.IsPointerType():
99 elem_ofst
= getfieldoffset(element_type
.GetPointeeType(), field_name
) + field_ofst
101 elem_ofst
= getfieldoffset(element_type
, field_name
) + field_ofst
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
)
113 def 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
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.
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
123 head
= queue_head
.head
.GetSBValue()
124 queue_head_addr
= 0x0
125 if head
.TypeIsPointerType():
126 queue_head_addr
= head
.GetValueAsUnsigned()
128 queue_head_addr
= head
.GetAddress().GetLoadAddress(osplugin_target_obj
)
131 if not cur_elt
.IsValid() or cur_elt
.GetValueAsUnsigned() == 0:
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
:
138 def IterateQueue(queue_head
, element_ptr_type
, element_field_name
, backwards
=False, unpack_ptr_fn
=None):
139 """ Iterate over an Element Chain queue in kernel of type queue_head_t. (osfmk/kern/queue.h method 2)
141 queue_head - value : Value object for queue_head.
142 element_ptr_type - lldb.SBType : a pointer type of the element 'next' points to. Typically its structs like thread, task etc..
143 - str : OR a string describing the type. ex. 'task *'
144 element_field_name - str : name of the field in target struct.
145 backwards - backwards : traverse the queue backwards
146 unpack_ptr_fn - function : a function ptr of signature def unpack_ptr(long v) which returns long.
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
151 for page_meta in IterateQueue(kern.globals.first_zone.pages.all_free, 'struct zone_page_metadata *', 'pages'):
154 if type(element_ptr_type
) == str :
155 element_ptr_type
= gettype(element_ptr_type
)
157 queue_head
= queue_head
.GetSBValue()
158 queue_head_addr
= 0x0
159 if queue_head
.TypeIsPointerType():
160 queue_head_addr
= queue_head
.GetValueAsUnsigned()
162 queue_head_addr
= queue_head
.GetAddress().GetLoadAddress(LazyTarget
.GetTarget())
164 def unpack_ptr_and_recast(v
):
165 if unpack_ptr_fn
is None:
167 v_unpacked
= unpack_ptr_fn(v
.GetValueAsUnsigned())
168 obj
= v
.CreateValueFromExpression(None,'(void *)'+str(v_unpacked
))
169 obj
.Cast(element_ptr_type
)
173 cur_elt
= unpack_ptr_and_recast(queue_head
.GetChildMemberWithName('prev'))
175 cur_elt
= unpack_ptr_and_recast(queue_head
.GetChildMemberWithName('next'))
179 if not cur_elt
.IsValid() or cur_elt
.GetValueAsUnsigned() == 0 or cur_elt
.GetValueAsUnsigned() == queue_head_addr
:
181 elt
= cur_elt
.Cast(element_ptr_type
)
184 cur_elt
= unpack_ptr_and_recast(elt
.GetChildMemberWithName(element_field_name
).GetChildMemberWithName('prev'))
186 cur_elt
= unpack_ptr_and_recast(elt
.GetChildMemberWithName(element_field_name
).GetChildMemberWithName('next'))
189 def 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
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
198 elt
= element
.__getattr
__('rbh_root')
199 if type(element_type
) == str:
200 element_type
= gettype(element_type
)
204 while unsigned(elt
) != 0:
206 elt
= cast(elt
.__getattr
__(field_name
).__getattr
__('rbe_left'), element_type
)
210 while unsigned(elt
) != 0:
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:
216 left
= cast(elt
.__getattr
__(field_name
).__getattr
__('rbe_left'), element_type
)
217 while unsigned(left
) != 0:
219 left
= cast(elt
.__getattr
__(field_name
).__getattr
__('rbe_left'), element_type
)
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
)
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
)):
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
)):
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
)
242 right
= cast(parent
.__getattr
__(field_name
).__getattr
__('rbe_right'), element_type
)
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
)
250 def IterateSchedPriorityQueue(root
, element_type
, field_name
):
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
256 A generator does not return. It is used for iterating
257 value : an object thats of type (element_type). Always a pointer object
260 return value(root
.GetSBValue().CreateValueFromExpression(None,'(struct priority_queue_entry_sched *)'+str(addr
)))
262 queue
= [unsigned(root
.pq_root
)]
265 elt
= _make_pqe(queue
.pop())
268 yield containerof(elt
, element_type
, field_name
)
269 addr
= unsigned(elt
.child
)
270 if addr
: queue
.append(addr
)
273 def 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
279 The sched pri of the root element.
282 return value(root
.GetSBValue().CreateValueFromExpression(None,'(struct priority_queue_entry_stable *)'+str(addr
)))
284 elt
= _make_pqe(unsigned(root
.pq_root
))
285 return (elt
.key
>> 8);
287 def 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
293 A generator does not return. It is used for iterating
294 value : an object thats of type (element_type). Always a pointer object
296 elt
= root
.mpqh_head
.mpqc_next
298 yield containerof(elt
, element_type
, field_name
)
301 class 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.
306 def __init__(self
, debugger
):
307 """ Initialize the kernel debugging environment.
308 Target properties like architecture and connectedness are lazy-evaluted.
310 self
._debugger
= debugger
# This holds an lldb.SBDebugger object for debugger state
311 self
._threads
_list
= []
312 self
._tasks
_list
= []
313 self
._coalitions
_list
= []
314 self
._thread
_groups
= []
316 self
._terminated
_tasks
_list
= []
317 self
._terminated
_threads
_list
= []
318 self
._zones
_list
= []
319 self
._zombproc
_list
= []
320 self
._kernel
_types
_cache
= {} #this will cache the Type objects as and when requested.
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
_12obscure
12 = kern
328 def __getattr__(self
, name
):
329 v
= self
._xnu
_kernobj
_12obscure
12.GetGlobalVariable(name
)
330 if not v
.GetSBValue().IsValid():
331 raise ValueError('No such global variable by name: %s '%str
(name
))
333 self
.globals = _GlobalVariableFind(self
)
334 LazyTarget
.Initialize(debugger
)
336 def _GetSymbolicator(self
):
337 """ Internal function: To initialize the symbolication from lldb.utils
339 if not self
.symbolicator
is None:
340 return self
.symbolicator
342 from lldb
.utils
import symbolication
343 symbolicator
= symbolication
.Symbolicator()
344 symbolicator
.target
= LazyTarget
.GetTarget()
345 self
.symbolicator
= symbolicator
346 return self
.symbolicator
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'
351 addr - int : typically hex value like 0xffffff80002c0df0
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()
357 syms
= self
.SymbolicateFromAddress(addr
)
359 ret_str
+=syms
[0].GetName()
362 def SymbolicateFromAddress(self
, addr
):
363 """ symbolicates any given address based on modules loaded in the target.
365 addr - int : typically hex value like 0xffffff80002c0df0
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.
370 syms = kern.Symbolicate(0xffffff80002c0df0)
372 if s.GetType() == lldb.eSymbolTypeCode:
373 print "Function", s.GetName()
374 if s.GetType() == lldb.eSymbolTypeData:
375 print "Variable", s.GetName()
377 if type(int(1)) != type(addr
):
378 if str(addr
).strip().find("0x") == 0 :
382 addr
= self
.StripKernelPAC(addr
)
384 symbolicator
= self
._GetSymbolicator
()
385 syms
= symbolicator
.symbolicate(addr
)
389 ret_array
.append(s
.get_symbol_context().symbol
)
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
397 def GetGlobalVariable(self
, name
):
398 """ Get the value object representation for a kernel global variable
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.
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
]
409 def GetLoadAddressForSymbol(self
, name
):
410 """ Get the load address of a symbol in the kernel.
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.
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()
422 return int(symbol
.GetStartAddress().GetLoadAddress(target
))
424 raise LookupError("Symbol not found: " + name
)
426 def GetValueFromAddress(self
, addr
, type_str
= 'void *'):
427 """ convert a address to value
429 addr - int : typically hex value like 0xffffff80008dc390
430 type_str - str: type to cast to. Default type will be void *
432 value : a value object which has address as addr and type is type_str
434 obj
= value(self
.globals.version
.GetSBValue().CreateValueFromExpression(None,'(void *)'+str(addr
)))
435 obj
= cast(obj
, type_str
)
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.
443 NameError - If 'v' cannot be found
444 TypeError - If 'v' is of the wrong type
447 return self
.GetValueFromAddress(v
, t
)
449 var
= LazyTarget
.GetTarget().FindGlobalVariables(v
, 1)[0]
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()))
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.
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.
463 iterable : typically used in conjunction with "for varname in iterable:"
465 head_element
= self
.GetGlobalVariable(iter_head_name
)
466 return head_element
.GetSBValue().linked_list_iter(next_element_name
)
468 def TruncPage(self
, addr
):
469 return (addr
& ~
(unsigned(self
.GetGlobalVariable("page_size")) - 1))
471 def RoundPage(self
, addr
):
472 return trunc_page(addr
+ unsigned(self
.GetGlobalVariable("page_size")) - 1)
474 def StraddlesPage(self
, addr
, size
):
475 if size
> unsigned(self
.GetGlobalVariable("page_size")):
477 val
= ((addr
+ size
) & (unsigned(self
.GetGlobalVariable("page_size"))-1))
478 return (val
< size
and val
> 0)
480 def StripUserPAC(self
, addr
):
481 if self
.arch
!= 'arm64e':
483 T0Sz
= self
.GetGlobalVariable('gT0Sz')
484 return StripPAC(addr
, T0Sz
)
486 def StripKernelPAC(self
, addr
):
487 if self
.arch
!= 'arm64e':
489 T1Sz
= self
.GetGlobalVariable('gT1Sz')
490 return StripPAC(addr
, T1Sz
)
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")))
499 def PhysToKernelVirt(self
, addr
):
500 if self
.arch
== 'x86_64':
501 return (addr
+ unsigned(self
.GetGlobalVariable('physmap_base')))
502 elif self
.arch
.startswith('arm64'):
503 return self
.PhysToKVARM64(addr
)
504 elif self
.arch
.startswith('arm'):
505 return (addr
- unsigned(self
.GetGlobalVariable("gPhysBase")) + unsigned(self
.GetGlobalVariable("gVirtBase")))
507 raise ValueError("PhysToVirt does not support {0}".format(self
.arch
))
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.
513 abstime - int absolute time as shown by mach_absolute_time
515 int - nanosecs of time
517 usec_divisor
= caching
.GetStaticCacheData("kern.rtc_usec_divisor", None)
519 if self
.arch
== 'x86_64':
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
530 def __getattribute__(self
, name
):
532 self
._zones
_list
= caching
.GetDynamicCacheData("kern._zones_list", [])
533 if len(self
._zones
_list
) > 0: return self
._zones
_list
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
]))
537 caching
.SaveDynamicCacheData("kern._zones_list", self
._zones
_list
)
538 return self
._zones
_list
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
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
562 if name
== 'coalitions' :
563 self
._coalitions
_list
= caching
.GetDynamicCacheData("kern._coalitions_list", [])
564 if len(self
._coalitions
_list
) > 0 : return self
._coalitions
_list
565 coalition_queue_head
= self
.GetGlobalVariable('coalitions_q')
566 coalition_type
= LazyTarget
.GetTarget().FindFirstType('coalition')
567 coalition_ptr_type
= coalition_type
.GetPointerType()
568 for coal
in IterateLinkageChain(addressof(coalition_queue_head
), coalition_ptr_type
, 'coalitions'):
569 self
._coalitions
_list
.append(coal
)
570 caching
.SaveDynamicCacheData("kern._coalitions_list", self
._coalitions
_list
)
571 return self
._coalitions
_list
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
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
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
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 *')
612 self
._allproc
.append(proc_val
)
613 proc_val
= cast(proc_val
.p_list
.le_next
, 'proc *')
614 caching
.SaveDynamicCacheData("kern._allproc", self
._allproc
)
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
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 *')
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
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
)
647 self
._arch
= caching
.GetStaticCacheData("kern.arch", None)
648 if self
._arch
!= None : return self
._arch
649 arch
= LazyTarget
.GetTarget().triple
.split('-')[0]
650 if arch
in ('armv7', 'armv7s', 'armv7k'):
654 caching
.SaveStaticCacheData("kern.arch", self
._arch
)
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]
661 if arch
== 'x86_64' or arch
.startswith('arm64'):
665 caching
.SaveStaticCacheData("kern.ptrsize", self
._ptrsize
)
668 if name
== 'VM_MIN_KERNEL_ADDRESS':
669 if self
.arch
== 'x86_64':
670 return unsigned(0xFFFFFF8000000000)
671 elif self
.arch
.startswith('arm64'):
672 return unsigned(0xffffffe000000000)
674 return unsigned(0x80000000)
676 if name
== 'VM_MIN_KERNEL_AND_KEXT_ADDRESS':
677 if self
.arch
== 'x86_64':
678 return self
.VM_MIN_KERNEL_ADDRESS
- 0x80000000
680 return self
.VM_MIN_KERNEL_ADDRESS
682 return object.__getattribute
__(self
, name
)