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