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