]>
git.saurik.com Git - apple/xnu.git/blob - tools/lldbmacros/core/kernelcore.py
d21b5c91269aaaf7553587b29e945963065af23f
   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
._zones
_list 
= [] 
 318         self
._zombproc
_list 
= [] 
 319         self
._kernel
_types
_cache 
= {} #this will cache the Type objects as and when requested. 
 322         self
._ptrsize 
= None # pointer size of kernel, not userspace 
 323         self
.symbolicator 
= None 
 324         class _GlobalVariableFind(object): 
 325             def __init__(self
, kern
): 
 326                 self
._xnu
_kernobj
_12obscure
12 = kern
 
 327             def __getattr__(self
, name
): 
 328                 v 
= self
._xnu
_kernobj
_12obscure
12.GetGlobalVariable(name
) 
 329                 if not v
.GetSBValue().IsValid(): 
 330                     raise ValueError('No such global variable by name: %s '%str
(name
)) 
 332         self
.globals = _GlobalVariableFind(self
) 
 333         LazyTarget
.Initialize(debugger
) 
 335     def _GetSymbolicator(self
): 
 336         """ Internal function: To initialize the symbolication from lldb.utils 
 338         if not self
.symbolicator 
is None: 
 339             return self
.symbolicator
 
 341         from lldb
.utils 
import symbolication
 
 342         symbolicator 
= symbolication
.Symbolicator() 
 343         symbolicator
.target 
= LazyTarget
.GetTarget() 
 344         self
.symbolicator 
= symbolicator
 
 345         return self
.symbolicator
 
 347     def Symbolicate(self
, addr
): 
 348         """ simple method to get name of function/variable from an address. this is equivalent of gdb 'output /a 0xaddress' 
 350                 addr - int : typically hex value like 0xffffff80002c0df0 
 352                 str - '' if no symbol found else the symbol name. 
 353             Note: this function only finds the first symbol. If you expect multiple symbol conflict please use SymbolicateFromAddress() 
 356         syms 
= self
.SymbolicateFromAddress(addr
) 
 358             ret_str 
+=syms
[0].GetName() 
 361     def SymbolicateFromAddress(self
, addr
): 
 362         """ symbolicates any given address based on modules loaded in the target. 
 364                 addr - int : typically hex value like 0xffffff80002c0df0 
 366                 [] of SBSymbol: In case we don't find anything than empty array is returned. 
 367                       Note: a type of symbol can be figured out by gettype() function of SBSymbol. 
 369                 syms = kern.Symbolicate(0xffffff80002c0df0) 
 371                   if s.GetType() == lldb.eSymbolTypeCode: 
 372                     print "Function", s.GetName() 
 373                   if s.GetType() == lldb.eSymbolTypeData: 
 374                     print "Variable", s.GetName() 
 376         if type(int(1)) != type(addr
): 
 377             if str(addr
).strip().find("0x") == 0 : 
 381         addr 
= self
.StripKernelPAC(addr
) 
 383         symbolicator 
= self
._GetSymbolicator
() 
 384         syms 
= symbolicator
.symbolicate(addr
) 
 388             ret_array
.append(s
.get_symbol_context().symbol
) 
 391     def IsDebuggerConnected(self
): 
 392         proc_state 
= LazyTarget
.GetProcess().state
 
 393         if proc_state 
== lldb
.eStateInvalid 
: return False 
 394         if proc_state 
in [lldb
.eStateStopped
, lldb
.eStateSuspended
] : return True 
 396     def GetGlobalVariable(self
, name
): 
 397         """ Get the value object representation for a kernel global variable 
 399               name : str - name of the variable. ex. version 
 400             returns: value - python object representing global variable. 
 401             raises : Exception in case the variable is not found. 
 403         self
._globals
_cache
_dict 
= caching
.GetDynamicCacheData("kern._globals_cache_dict", {}) 
 404         if name 
not in self
._globals
_cache
_dict
: 
 405             self
._globals
_cache
_dict
[name
] = value(LazyTarget
.GetTarget().FindGlobalVariables(name
, 1).GetValueAtIndex(0)) 
 406         return self
._globals
_cache
_dict
[name
] 
 408     def GetLoadAddressForSymbol(self
, name
): 
 409         """ Get the load address of a symbol in the kernel. 
 411               name : str - name of the symbol to lookup 
 412             returns: int - the load address as an integer. Use GetValueFromAddress to cast to a value. 
 413             raises : LookupError - if the symbol is not found. 
 416         target 
= LazyTarget
.GetTarget() 
 417         syms_arr 
= target
.FindSymbols(name
) 
 418         if syms_arr
.IsValid() and len(syms_arr
) > 0: 
 419             symbol 
= syms_arr
[0].GetSymbol() 
 421                 return int(symbol
.GetStartAddress().GetLoadAddress(target
)) 
 423         raise LookupError("Symbol not found: " + name
) 
 425     def GetValueFromAddress(self
, addr
, type_str 
= 'void *'): 
 426         """ convert a address to value 
 428                 addr - int : typically hex value like 0xffffff80008dc390 
 429                 type_str - str: type to cast to. Default type will be void * 
 431                 value : a value object which has address as addr and type is type_str 
 433         obj 
= value(self
.globals.version
.GetSBValue().CreateValueFromExpression(None,'(void *)'+str(addr
))) 
 434         obj 
= cast(obj
, type_str
) 
 437     def GetValueAsType(self
, v
, t
): 
 438         """ Retrieves a global variable 'v' of type 't' wrapped in a vue object. 
 439             If 'v' is an address, creates a vue object of the appropriate type. 
 440             If 'v' is a name, looks for the global variable and asserts its type. 
 442                 NameError - If 'v' cannot be found 
 443                 TypeError - If 'v' is of the wrong type 
 446             return self
.GetValueFromAddress(v
, t
) 
 448             var 
= LazyTarget
.GetTarget().FindGlobalVariables(v
, 1)[0] 
 450                 raise NameError("Failed to find global variable '{0}'".format(v
)) 
 451             if var
.GetTypeName() != t
: 
 452                 raise TypeError("{0} must be of type '{1}', not '{2}'".format(v
, t
, var
.GetTypeName())) 
 455     def _GetIterator(self
, iter_head_name
, next_element_name
='next', iter_head_type
=None): 
 456         """ returns an iterator for a collection in kernel memory. 
 458                 iter_head_name - str : name of queue_head or list head variable. 
 459                 next_element_name - str : name of the element that leads to next element. 
 460                                           for ex. in struct zone list 'next_zone' is the linking element. 
 462                 iterable : typically used in conjunction with "for varname in iterable:" 
 464         head_element 
= self
.GetGlobalVariable(iter_head_name
) 
 465         return head_element
.GetSBValue().linked_list_iter(next_element_name
) 
 467     def TruncPage(self
, addr
): 
 468         return (addr 
& ~
(unsigned(self
.GetGlobalVariable("page_size")) - 1)) 
 470     def RoundPage(self
, addr
): 
 471         return trunc_page(addr 
+ unsigned(self
.GetGlobalVariable("page_size")) - 1) 
 473     def StraddlesPage(self
, addr
, size
): 
 474         if size 
> unsigned(self
.GetGlobalVariable("page_size")): 
 476         val 
= ((addr 
+ size
) & (unsigned(self
.GetGlobalVariable("page_size"))-1)) 
 477         return (val 
< size 
and val 
> 0) 
 479     def StripUserPAC(self
, addr
): 
 480         if self
.arch 
!= 'arm64e': 
 482         T0Sz 
= self
.GetGlobalVariable('gT0Sz') 
 483         return StripPAC(addr
, T0Sz
) 
 485     def StripKernelPAC(self
, addr
): 
 486         if self
.arch 
!= 'arm64e': 
 488         T1Sz 
= self
.GetGlobalVariable('gT1Sz') 
 489         return StripPAC(addr
, T1Sz
) 
 491     def PhysToKVARM64(self
, addr
): 
 492         ptov_table 
= self
.GetGlobalVariable('ptov_table') 
 493         for i 
in range(0, self
.GetGlobalVariable('ptov_index')): 
 494             if (addr 
>= long(unsigned(ptov_table
[i
].pa
))) and (addr 
< (long(unsigned(ptov_table
[i
].pa
)) + long(unsigned(ptov_table
[i
].len)))): 
 495                 return (addr 
- long(unsigned(ptov_table
[i
].pa
)) + long(unsigned(ptov_table
[i
].va
))) 
 496         return (addr 
- unsigned(self
.GetGlobalVariable("gPhysBase")) + unsigned(self
.GetGlobalVariable("gVirtBase"))) 
 498     def PhysToKernelVirt(self
, addr
): 
 499         if self
.arch 
== 'x86_64': 
 500             return (addr 
+ unsigned(self
.GetGlobalVariable('physmap_base'))) 
 501         elif self
.arch
.startswith('arm64'): 
 502             return self
.PhysToKVARM64(addr
) 
 503         elif self
.arch
.startswith('arm'): 
 504             return (addr 
- unsigned(self
.GetGlobalVariable("gPhysBase")) + unsigned(self
.GetGlobalVariable("gVirtBase"))) 
 506             raise ValueError("PhysToVirt does not support {0}".format(self
.arch
)) 
 508     def GetNanotimeFromAbstime(self
, abstime
): 
 509         """ convert absolute time (which is in MATUs) to nano seconds. 
 510             Since based on architecture the conversion may differ. 
 512                 abstime - int absolute time as shown by mach_absolute_time 
 514                 int - nanosecs of time 
 516         usec_divisor 
= caching
.GetStaticCacheData("kern.rtc_usec_divisor", None) 
 518             if self
.arch 
== 'x86_64': 
 521                 rtclockdata_addr 
= self
.GetLoadAddressForSymbol('RTClockData') 
 522                 rtc 
= self
.GetValueFromAddress(rtclockdata_addr
, 'struct _rtclock_data_ *') 
 523                 usec_divisor 
= unsigned(rtc
.rtc_usec_divisor
) 
 524             usec_divisor 
= int(usec_divisor
) 
 525             caching
.SaveStaticCacheData('kern.rtc_usec_divisor', usec_divisor
) 
 526         nsecs 
= (abstime 
* 1000)/usec_divisor
 
 529     def __getattribute__(self
, name
): 
 531             self
._zones
_list 
= caching
.GetDynamicCacheData("kern._zones_list", []) 
 532             if len(self
._zones
_list
) > 0: return self
._zones
_list
 
 533             zone_array 
= self
.GetGlobalVariable('zone_array') 
 534             for i 
in range(0, self
.GetGlobalVariable('num_zones')): 
 535                 self
._zones
_list
.append(addressof(zone_array
[i
])) 
 536             caching
.SaveDynamicCacheData("kern._zones_list", self
._zones
_list
) 
 537             return self
._zones
_list
 
 539         if name 
== 'threads' : 
 540             self
._threads
_list 
= caching
.GetDynamicCacheData("kern._threads_list", []) 
 541             if len(self
._threads
_list
) > 0 : return self
._threads
_list
 
 542             thread_queue_head 
= self
.GetGlobalVariable('threads') 
 543             thread_type 
= LazyTarget
.GetTarget().FindFirstType('thread') 
 544             thread_ptr_type 
= thread_type
.GetPointerType() 
 545             for th 
in IterateQueue(thread_queue_head
, thread_ptr_type
, 'threads'): 
 546                 self
._threads
_list
.append(th
) 
 547             caching
.SaveDynamicCacheData("kern._threads_list", self
._threads
_list
) 
 548             return self
._threads
_list
 
 551             self
._tasks
_list 
= caching
.GetDynamicCacheData("kern._tasks_list", []) 
 552             if len(self
._tasks
_list
) > 0 : return self
._tasks
_list
 
 553             task_queue_head 
= self
.GetGlobalVariable('tasks') 
 554             task_type 
= LazyTarget
.GetTarget().FindFirstType('task') 
 555             task_ptr_type 
= task_type
.GetPointerType() 
 556             for tsk 
in IterateQueue(task_queue_head
, task_ptr_type
, 'tasks'): 
 557                 self
._tasks
_list
.append(tsk
) 
 558             caching
.SaveDynamicCacheData("kern._tasks_list", self
._tasks
_list
) 
 559             return self
._tasks
_list
 
 561         if name 
== 'coalitions' : 
 562             self
._coalitions
_list 
= caching
.GetDynamicCacheData("kern._coalitions_list", []) 
 563             if len(self
._coalitions
_list
) > 0 : return self
._coalitions
_list
 
 564             coalition_queue_head 
= self
.GetGlobalVariable('coalitions_q') 
 565             coalition_type 
= LazyTarget
.GetTarget().FindFirstType('coalition') 
 566             coalition_ptr_type 
= coalition_type
.GetPointerType() 
 567             for coal 
in IterateLinkageChain(addressof(coalition_queue_head
), coalition_ptr_type
, 'coalitions'): 
 568                 self
._coalitions
_list
.append(coal
) 
 569             caching
.SaveDynamicCacheData("kern._coalitions_list", self
._coalitions
_list
) 
 570             return self
._coalitions
_list
 
 572         if name 
== 'thread_groups' : 
 573             self
._thread
_groups
_list 
= caching
.GetDynamicCacheData("kern._thread_groups_list", []) 
 574             if len(self
._thread
_groups
_list
) > 0 : return self
._thread
_groups
_list
 
 575             thread_groups_queue_head 
= self
.GetGlobalVariable('tg_queue') 
 576             thread_group_type 
= LazyTarget
.GetTarget().FindFirstType('thread_group') 
 577             thread_groups_ptr_type 
= thread_group_type
.GetPointerType() 
 578             for coal 
in IterateLinkageChain(addressof(thread_groups_queue_head
), thread_groups_ptr_type
, 'tg_queue_chain'): 
 579                 self
._thread
_groups
_list
.append(coal
) 
 580             caching
.SaveDynamicCacheData("kern._thread_groups_list", self
._thread
_groups
_list
) 
 581             return self
._thread
_groups
_list
 
 583         if name 
== 'terminated_tasks' : 
 584             self
._terminated
_tasks
_list 
= caching
.GetDynamicCacheData("kern._terminated_tasks_list", []) 
 585             if len(self
._terminated
_tasks
_list
) > 0 : return self
._terminated
_tasks
_list
 
 586             task_queue_head 
= self
.GetGlobalVariable('terminated_tasks') 
 587             task_type 
= LazyTarget
.GetTarget().FindFirstType('task') 
 588             task_ptr_type 
= task_type
.GetPointerType() 
 589             for tsk 
in IterateQueue(task_queue_head
, task_ptr_type
, 'tasks'): 
 590                 self
._terminated
_tasks
_list
.append(tsk
) 
 591             caching
.SaveDynamicCacheData("kern._terminated_tasks_list", self
._terminated
_tasks
_list
) 
 592             return self
._terminated
_tasks
_list
 
 595             self
._allproc 
= caching
.GetDynamicCacheData("kern._allproc", []) 
 596             if len(self
._allproc
) > 0 : return self
._allproc
 
 597             all_proc_head 
= self
.GetGlobalVariable('allproc') 
 598             proc_val 
= cast(all_proc_head
.lh_first
, 'proc *') 
 600                 self
._allproc
.append(proc_val
) 
 601                 proc_val 
= cast(proc_val
.p_list
.le_next
, 'proc *') 
 602             caching
.SaveDynamicCacheData("kern._allproc", self
._allproc
) 
 605         if name 
== 'interrupt_stats' : 
 606             self
._interrupt
_stats
_list 
= caching
.GetDynamicCacheData("kern._interrupt_stats_list", []) 
 607             if len(self
._interrupt
_stats
_list
) > 0 : return self
._interrupt
_stats
_list
 
 608             interrupt_stats_head 
= self
.GetGlobalVariable('gInterruptAccountingDataList') 
 609             interrupt_stats_type 
= LazyTarget
.GetTarget().FindFirstType('IOInterruptAccountingData') 
 610             interrupt_stats_ptr_type 
= interrupt_stats_type
.GetPointerType() 
 611             for interrupt_stats_obj 
in IterateQueue(interrupt_stats_head
, interrupt_stats_ptr_type
, 'chain'): 
 612                 self
._interrupt
_stats
_list
.append(interrupt_stats_obj
) 
 613             caching
.SaveDynamicCacheData("kern._interrupt_stats", self
._interrupt
_stats
_list
) 
 614             return self
._interrupt
_stats
_list
 
 616         if name 
== 'zombprocs' : 
 617             self
._zombproc
_list 
= caching
.GetDynamicCacheData("kern._zombproc_list", []) 
 618             if len(self
._zombproc
_list
) > 0 : return self
._zombproc
_list
 
 619             zproc_head 
= self
.GetGlobalVariable('zombproc') 
 620             proc_val 
= cast(zproc_head
.lh_first
, 'proc *') 
 622                 self
._zombproc
_list
.append(proc_val
) 
 623                 proc_val 
= cast(proc_val
.p_list
.le_next
, 'proc *') 
 624             caching
.SaveDynamicCacheData("kern._zombproc_list", self
._zombproc
_list
) 
 625             return self
._zombproc
_list
 
 627         if name 
== 'version' : 
 628             self
._version 
= caching
.GetStaticCacheData("kern.version", None) 
 629             if self
._version 
!= None : return self
._version
 
 630             self
._version 
= str(self
.GetGlobalVariable('version')) 
 631             caching
.SaveStaticCacheData("kern.version", self
._version
) 
 635             self
._arch 
= caching
.GetStaticCacheData("kern.arch", None) 
 636             if self
._arch 
!= None : return self
._arch
 
 637             arch 
= LazyTarget
.GetTarget().triple
.split('-')[0] 
 638             if arch 
in ('armv7', 'armv7s', 'armv7k'): 
 642             caching
.SaveStaticCacheData("kern.arch", self
._arch
) 
 645         if name 
== 'ptrsize' : 
 646             self
._ptrsize 
= caching
.GetStaticCacheData("kern.ptrsize", None) 
 647             if self
._ptrsize 
!= None : return self
._ptrsize
 
 648             arch 
= LazyTarget
.GetTarget().triple
.split('-')[0] 
 649             if arch 
== 'x86_64' or arch
.startswith('arm64'): 
 653             caching
.SaveStaticCacheData("kern.ptrsize", self
._ptrsize
) 
 656         if name 
== 'VM_MIN_KERNEL_ADDRESS': 
 657             if self
.arch 
== 'x86_64': 
 658                 return unsigned(0xFFFFFF8000000000) 
 659             elif self
.arch
.startswith('arm64'): 
 660                 return unsigned(0xffffffe000000000) 
 662                 return unsigned(0x80000000) 
 664         if name 
== 'VM_MIN_KERNEL_AND_KEXT_ADDRESS': 
 665             if self
.arch 
== 'x86_64': 
 666                 return self
.VM_MIN_KERNEL_ADDRESS 
- 0x80000000 
 668                 return self
.VM_MIN_KERNEL_ADDRESS
 
 670         return object.__getattribute
__(self
, name
)