]> git.saurik.com Git - apple/xnu.git/blob - tools/lldbmacros/ioreg.py
xnu-2422.1.72.tar.gz
[apple/xnu.git] / tools / lldbmacros / ioreg.py
1 from xnu import *
2 from utils import *
3 import sys
4
5 ######################################
6 # Globals
7 ######################################
8 plane = None
9
10 ######################################
11 # Type Summaries
12 ######################################
13 @lldb_type_summary(['OSObject *'])
14 @header("")
15 def GetObjectSummary(obj):
16 """ Show info about an OSObject - its vtable ptr and retain count, & more info for simple container classes.
17 """
18 if obj is None:
19 return
20
21 vt = dereference(Cast(obj, 'uintptr_t *')) - 2 * sizeof('uintptr_t')
22 vtype = kern.SymbolicateFromAddress(vt)
23 if hasattr(obj, 'retainCount'):
24 retCount = (obj.retainCount & 0xffff)
25 cntnrRetCount = (retCount >> 16)
26 out_string = "`object 0x{0: <16x}, vt 0x{1: <16x} <{2:s}>, retain count {3:d}, container retain {4:d}` ".format(obj, vt, vtype[0].GetName(), retCount, cntnrRetCount)
27 else:
28 if len(vtype):
29 out_string = "`object 0x{0: <16x}, vt 0x{1: <16x} <{2:s}>` ".format(obj, vt, vtype[0].GetName())
30 else:
31 out_string = "`object 0x{0: <16x}, vt 0x{1: <16x}` ".format(obj, vt)
32
33 ztvAddr = kern.GetLoadAddressForSymbol('_ZTV8OSString')
34 if vt == ztvAddr:
35 out_string += GetString(obj)
36 return out_string
37
38 ztvAddr = kern.GetLoadAddressForSymbol('_ZTV8OSSymbol')
39 if vt == ztvAddr:
40 out_string += GetString(obj)
41 return out_string
42
43 ztvAddr = kern.GetLoadAddressForSymbol('_ZTV8OSNumber')
44 if vt == ztvAddr:
45 out_string += GetNumber(obj)
46 return out_string
47
48 ztvAddr = kern.GetLoadAddressForSymbol('_ZTV9OSBoolean')
49 if vt == ztvAddr:
50 out_string += GetBoolean(obj)
51 return out_string
52
53 ztvAddr = kern.GetLoadAddressForSymbol('_ZTV7OSArray')
54 if vt == ztvAddr:
55 out_string += "(" + GetArray(Cast(obj, 'OSArray *')) + ")"
56 return out_string
57
58 ztvAddr = kern.GetLoadAddressForSymbol('_ZTV5OSSet')
59 if vt == ztvAddr:
60 out_string += GetSet(Cast(obj, 'OSSet *'))
61 return out_string
62
63 ztvAddr = kern.GetLoadAddressForSymbol('_ZTV12OSDictionary')
64 if vt == ztvAddr:
65 out_string += GetDictionary(Cast(obj, 'OSDictionary *'))
66 return out_string
67
68 return out_string
69
70 @lldb_type_summary(['IORegistryEntry *'])
71 @header("")
72 def GetRegistryEntrySummary(entry):
73 """ returns a string containing summary information about an IORegistry
74 object including it's registry id , vtable ptr and retain count
75 """
76 name = None
77 out_string = ""
78 registryTable = entry.fRegistryTable
79 propertyTable = entry.fPropertyTable
80
81 name = LookupKeyInOSDict(registryTable, kern.globals.gIOServicePlane.nameKey)
82 if name is None:
83 name = LookupKeyInOSDict(registryTable, kern.globals.gIONameKey)
84 if name is None:
85 name = LookupKeyInOSDict(propertyTable, kern.globals.gIOClassKey)
86
87 if name is not None:
88 out_string += "+-o {0:s} ".format(GetString(Cast(name, 'OSString *')))
89 elif Cast(entry, 'IOService *').pwrMgt and Cast(entry, 'IOService *').pwrMgt.Name:
90 out_string += "+-o {0:s} ".format(Cast(entry, 'IOService *').pwrMgt.Name)
91 else:
92 out_string += "+-o ?? "
93
94 # I'm using uintptr_t for now to work around <rdar://problem/12749733> FindFirstType & Co. should allow you to make pointer types directly
95 vtableAddr = dereference(Cast(entry, 'uintptr_t *')) - 2 * sizeof('uintptr_t *')
96 vtype = kern.SymbolicateFromAddress(vtableAddr)
97 if vtype is None or len(vtype) < 1:
98 out_string += "<object 0x{0: <16x}, id 0x{1:x}, vtable 0x{2: <16x}".format(entry, entry.reserved.fRegistryEntryID, vtableAddr)
99 else:
100 out_string += "<object 0x{0: <16x}, id 0x{1:x}, vtable 0x{2: <16x} <{3:s}>".format(entry, entry.reserved.fRegistryEntryID, vtableAddr, vtype[0].GetName())
101
102 ztvAddr = kern.GetLoadAddressForSymbol('_ZTV15IORegistryEntry')
103 if vtableAddr != ztvAddr:
104 out_string += ", "
105 state = Cast(entry, 'IOService *').__state[0]
106 # kIOServiceRegisteredState
107 if 0 == state & 2:
108 out_string += "!"
109 out_string += "registered, "
110 # kIOServiceMatchedState
111 if 0 == state & 4:
112 out_string += "!"
113 out_string += "matched, "
114 #kIOServiceInactiveState
115 if 0 != state & 1:
116 out_string += "in"
117 busyCount = (Cast(entry, 'IOService *').__state[1] & 0xff)
118 retCount = (Cast(entry, 'IOService *').retainCount & 0xffff)
119 out_string += "active, busy {0}, retain count {1}>".format(busyCount, retCount)
120 #else:
121 # out_string += "\n"
122 return out_string
123
124 ######################################
125 # Commands
126 ######################################
127 @lldb_command('showallclasses')
128 def ShowAllClasses(cmd_args=None):
129 """ Show the instance counts and ivar size of all OSObject subclasses.
130 See ioclasscount man page for details
131 """
132 idx = 0
133 count = unsigned(kern.globals.sAllClassesDict.count)
134
135 while idx < count:
136 meta = Cast(kern.globals.sAllClassesDict.dictionary[idx].value, 'OSMetaClass *')
137 idx += 1
138 print GetMetaClass(meta)
139
140 @lldb_command('showobject')
141 def ShowObject(cmd_args=None):
142 """ Show info about an OSObject - its vtable ptr and retain count, & more info for simple container classes.
143 """
144 if not cmd_args:
145 print "Please specify the address of the OSObject whose info you want to view. Type help showobject for help"
146 return
147
148 obj = kern.GetValueFromAddress(cmd_args[0], 'OSObject *')
149 print GetObjectSummary(obj)
150
151 @lldb_command('setregistryplane')
152 def SetRegistryPlane(cmd_args=None):
153 """ Set the plane to be used for the IOKit registry macros
154 syntax: (lldb) setregistryplane 0 - will display all known planes
155 syntax: (lldb) setregistryplane 0xaddr - will set the registry plane to 0xaddr
156 syntax: (lldb) setregistryplane gIODTPlane - will set the registry plane to gIODTPlane
157 """
158 if not cmd_args:
159 print "Please specify the name of the plane you want to use with the IOKit registry macros."
160 print SetRegistryPlane.__doc__
161
162 if cmd_args[0] == "0":
163 print GetObjectSummary(kern.globals.gIORegistryPlanes)
164 else:
165 global plane
166 plane = kern.GetValueFromAddress(cmd_args[0], 'IORegistryPlane *')
167 return
168
169 @lldb_command('showregistryentry')
170 def ShowRegistryEntry(cmd_args=None):
171 """ Show info about a registry entry; its properties and descendants in the current plane
172 syntax: (lldb) showregistryentry 0xaddr
173 syntax: (lldb) showregistryentry gIOPMRootDomain
174 """
175 if not cmd_args:
176 print "Please specify the address of the registry entry whose info you want to view."
177 print ShowRegistryEntry.__doc__
178 return
179
180 entry = kern.GetValueFromAddress(cmd_args[0], 'IORegistryEntry *')
181 ShowRegistryEntryRecurse(entry, "", True)
182
183 @lldb_command('showregistry')
184 def ShowRegistry(cmd_args=None):
185 """ Show info about all registry entries in the current plane
186 If prior to invoking this command no registry plane is specified
187 using 'setregistryplane', the command defaults to the IOService plane
188 """
189 ShowRegistryEntryRecurse(kern.globals.gRegistryRoot, "", False)
190
191 @lldb_command('showregistryprops')
192 def ShowRegistryProps(cmd_args=None):
193 """ Show info about all registry entries in the current plane, and their properties
194 If prior to invoking this command no registry plane is specified
195 using 'setregistryplane', the command defaults to the IOService plane
196 """
197 ShowRegistryEntryRecurse(kern.globals.gRegistryRoot, "", True)
198
199 @lldb_command('findregistryentry')
200 def FindRegistryEntry(cmd_args=None):
201 """ Search for registry entry that matches the given string
202 If prior to invoking this command no registry plane is specified
203 using 'setregistryplane', the command defaults to searching entries from the IOService plane
204 syntax: (lldb) findregistryentries AppleACPICPU - will find the first registry entry that matches AppleACPICPU
205 """
206 if not cmd_args:
207 print "Please specify the name of the registry entry you want to find"
208 print FindRegistryEntry.__doc__
209 return
210
211 FindRegistryEntryRecurse(kern.globals.gRegistryRoot, cmd_args[0], True)
212
213 @lldb_command('findregistryentries')
214 def FindRegistryEntries(cmd_args=None):
215 """ Search for all registry entries that match the given string
216 If prior to invoking this command no registry plane is specified
217 using 'setregistryplane', the command defaults to searching entries from the IOService plane
218 syntax: (lldb) findregistryentries AppleACPICPU - will find all registry entries that match AppleACPICPU
219 """
220 if not cmd_args:
221 print "Please specify the name of the registry entry/entries you want to find"
222 print FindRegistryEntries.__doc__
223 return
224
225 FindRegistryEntryRecurse(kern.globals.gRegistryRoot, cmd_args[0], False)
226
227 @lldb_command('findregistryprop')
228 def FindRegistryProp(cmd_args=None):
229 """ Given a registry entry, print out the contents for the property that matches
230 a specific string
231 syntax: (lldb) findregistryprop 0xaddr IOSleepSupported
232 syntax: (lldb) findregistryprop gIOPMRootDomain IOSleepSupported
233 syntax: (lldb) findregistryprop gIOPMRootDomain "Supported Features"
234 """
235 if not cmd_args or len(cmd_args) < 2:
236 print "Please specify the address of a IORegistry entry and the property you're looking for"
237 print FindRegistryProp.__doc__
238 return
239
240 entry = kern.GetValueFromAddress(cmd_args[0], 'IOService *')
241 propertyTable = entry.fPropertyTable
242 print GetObjectSummary(LookupKeyInPropTable(propertyTable, cmd_args[1]))
243
244 @lldb_command('readioport8')
245 def ReadIOPort8(cmd_args=None):
246 """ Read value stored in the specified IO port. The CPU can be optionally
247 specified as well.
248 Prints 0xBAD10AD in case of a bad read
249 Syntax: (lldb) readioport8 <port> [lcpu (kernel's numbering convention)]
250 """
251 if not cmd_args:
252 print "Please specify a port to read out of"
253 print ReadIOPort8.__doc__
254 return
255
256 portAddr = ArgumentStringToInt(cmd_args[0])
257 if len(cmd_args) >= 2:
258 lcpu = ArgumentStringToInt(cmd_args[1])
259 else:
260 lcpu = xnudefines.lcpu_self
261
262 ReadIOPortInt(portAddr, 1, lcpu)
263
264 @lldb_command('readioport16')
265 def ReadIOPort8(cmd_args=None):
266 """ Read value stored in the specified IO port. The CPU can be optionally
267 specified as well.
268 Prints 0xBAD10AD in case of a bad read
269 Syntax: (lldb) readioport16 <port> [lcpu (kernel's numbering convention)]
270 """
271 if not cmd_args:
272 print "Please specify a port to read out of"
273 print ReadIOPort16.__doc__
274 return
275
276 portAddr = ArgumentStringToInt(cmd_args[0])
277 if len(cmd_args) >= 2:
278 lcpu = ArgumentStringToInt(cmd_args[1])
279 else:
280 lcpu = xnudefines.lcpu_self
281
282 ReadIOPortInt(portAddr, 2, lcpu)
283
284 @lldb_command('readioport32')
285 def ReadIOPort8(cmd_args=None):
286 """ Read value stored in the specified IO port. The CPU can be optionally
287 specified as well.
288 Prints 0xBAD10AD in case of a bad read
289 Syntax: (lldb) readioport32 <port> [lcpu (kernel's numbering convention)]
290 """
291 if not cmd_args:
292 print "Please specify a port to read out of"
293 print ReadIOPort32.__doc__
294 return
295
296 portAddr = ArgumentStringToInt(cmd_args[0])
297 if len(cmd_args) >= 2:
298 lcpu = ArgumentStringToInt(cmd_args[1])
299 else:
300 lcpu = xnudefines.lcpu_self
301
302 ReadIOPortInt(portAddr, 4, lcpu)
303
304 @lldb_command('writeioport8')
305 def WriteIOPort8(cmd_args=None):
306 """ Write the value to the specified IO port. The size of the value is
307 determined by the name of the command. The CPU used can be optionally
308 specified as well.
309 Syntax: (lldb) writeioport8 <port> <value> [lcpu (kernel's numbering convention)]
310 """
311 if not cmd_args or len(cmd_args) < 2:
312 print "Please specify a port to write to, followed by the value you want to write"
313 print WriteIOPort8.__doc__
314 return
315
316 portAddr = ArgumentStringToInt(cmd_args[0])
317 value = ArgumentStringToInt(cmd_args[1])
318
319 if len(cmd_args) >= 3:
320 lcpu = ArgumentStringToInt(cmd_args[2])
321 else:
322 lcpu = xnudefines.lcpu_self
323
324 WriteIOPortInt(portAddr, 1, value, lcpu)
325
326 @lldb_command('writeioport16')
327 def WriteIOPort8(cmd_args=None):
328 """ Write the value to the specified IO port. The size of the value is
329 determined by the name of the command. The CPU used can be optionally
330 specified as well.
331 Syntax: (lldb) writeioport16 <port> <value> [lcpu (kernel's numbering convention)]
332 """
333 if not cmd_args or len(cmd_args) < 2:
334 print "Please specify a port to write to, followed by the value you want to write"
335 print WriteIOPort16.__doc__
336 return
337
338 portAddr = ArgumentStringToInt(cmd_args[0])
339 value = ArgumentStringToInt(cmd_args[1])
340
341 if len(cmd_args) >= 3:
342 lcpu = ArgumentStringToInt(cmd_args[2])
343 else:
344 lcpu = xnudefines.lcpu_self
345
346 WriteIOPortInt(portAddr, 2, value, lcpu)
347
348 @lldb_command('writeioport32')
349 def WriteIOPort8(cmd_args=None):
350 """ Write the value to the specified IO port. The size of the value is
351 determined by the name of the command. The CPU used can be optionally
352 specified as well.
353 Syntax: (lldb) writeioport32 <port> <value> [lcpu (kernel's numbering convention)]
354 """
355 if not cmd_args or len(cmd_args) < 2:
356 print "Please specify a port to write to, followed by the value you want to write"
357 print WriteIOPort32.__doc__
358 return
359
360 portAddr = ArgumentStringToInt(cmd_args[0])
361 value = ArgumentStringToInt(cmd_args[1])
362
363 if len(cmd_args) >= 3:
364 lcpu = ArgumentStringToInt(cmd_args[2])
365 else:
366 lcpu = xnudefines.lcpu_self
367
368 WriteIOPortInt(portAddr, 4, value, lcpu)
369
370 @lldb_command('showioservicepm')
371 def ShowIOServicePM(cmd_args=None):
372 """ Routine to dump the IOServicePM object
373 Syntax: (lldb) showioservicepm <IOServicePM pointer>
374 """
375 if not cmd_args:
376 print "Please enter the pointer to the IOServicePM object you'd like to introspect"
377 print ShowIOServicePM.__doc__
378 return
379
380 iopmpriv = kern.GetValueFromAddress(cmd_args[0], 'IOServicePM *')
381 out_string = "MachineState {0: <6d} (".format(iopmpriv.MachineState)
382
383 # Power state map
384 pstate_map = {
385 0: 'kIOPM_Finished',
386 1: 'kIOPM_OurChangeTellClientsPowerDown',
387 2: 'kIOPM_OurChangeTellClientsPowerDown',
388 3: 'kIOPM_OurChangeNotifyInterestedDriversWillChange',
389 4: 'kIOPM_OurChangeSetPowerState',
390 5: 'kIOPM_OurChangeWaitForPowerSettle',
391 6: 'kIOPM_OurChangeNotifyInterestedDriversDidChange',
392 7: 'kIOPM_OurChangeTellCapabilityDidChange',
393 8: 'kIOPM_OurChangeFinish',
394 9: 'Unused_MachineState_9',
395 10: 'kIOPM_ParentChangeTellPriorityClientsPowerDown',
396 11: 'kIOPM_ParentChangeNotifyInterestedDriversWillChange',
397 12: 'kIOPM_ParentChangeSetPowerState',
398 13: 'kIOPM_ParentChangeWaitForPowerSettle',
399 14: 'kIOPM_ParentChangeNotifyInterestedDriversDidChange',
400 15: 'kIOPM_ParentChangeTellCapabilityDidChange',
401 16: 'kIOPM_ParentChangeAcknowledgePowerChange',
402 17: 'kIOPM_NotifyChildrenStart',
403 18: 'kIOPM_NotifyChildrenOrdered',
404 19: 'kIOPM_NotifyChildrenDelayed',
405 20: 'kIOPM_SyncTellClientsPowerDown',
406 21: 'kIOPM_SyncTellPriorityClientsPowerDown',
407 22: 'kIOPM_SyncNotifyWillChange',
408 23: 'kIOPM_SyncNotifyDidChange',
409 24: 'kIOPM_SyncTellCapabilityDidChange',
410 25: 'kIOPM_SyncFinish',
411 26: 'kIOPM_TellCapabilityChangeDone',
412 27: 'kIOPM_DriverThreadCallDone'
413 }
414 powerstate = unsigned(iopmpriv.MachineState)
415 if powerstate in pstate_map:
416 out_string += "{0:s}".format(pstate_map[powerstate])
417 else:
418 out_string += "Unknown_MachineState"
419 out_string += "), "
420
421 if iopmpriv.MachineState != 20:
422 out_string += "DriverTimer = {0: <6d}, SettleTime = {1: < 6d}, HeadNoteFlags = {2: #12x}, HeadNotePendingAcks = {3: #012x}, ".format(
423 unsigned(iopmpriv.DriverTimer),
424 unsigned(iopmpriv.SettleTimeUS),
425 unsigned(iopmpriv.HeadNoteChangeFlags),
426 unsigned(iopmpriv.HeadNotePendingAcks))
427
428 if iopmpriv.DeviceOverrideEnabled != 0:
429 out_string += "DeviceOverrides, "
430
431 out_string += "DeviceDesire = {0: <6d}, DesiredPowerState = {1: <6d}, PreviousRequest = {2: <6d}\n".format(
432 unsigned(iopmpriv.DeviceDesire),
433 unsigned(iopmpriv.DesiredPowerState),
434 unsigned(iopmpriv.PreviousRequestPowerFlags))
435
436 print out_string
437
438 ######################################
439 # Helper routines
440 ######################################
441 def ShowRegistryEntryRecurse(entry, prefix, printProps):
442 """ prints registry entry summary and recurses through all its children.
443 """
444 # Setup
445 global plane
446 out_string = ""
447 plen = (len(prefix)//2)
448 registryTable = entry.fRegistryTable
449 propertyTable = entry.fPropertyTable
450
451 # Print entry details
452 print "{0:s}{1:s}".format(prefix, GetRegistryEntrySummary(entry))
453 # Printing large property tables make it look like lldb is 'stuck'
454 if printProps:
455 print GetRegDictionary(propertyTable, prefix + " | ")
456
457 # Recurse
458 if plane is None:
459 childKey = kern.globals.gIOServicePlane.keys[1]
460 else:
461 childKey = plane.keys[1]
462 childArray = LookupKeyInOSDict(registryTable, childKey)
463 if childArray is not None:
464 idx = 0
465 ca = Cast(childArray, 'OSArray *')
466 count = unsigned(ca.count)
467 while idx < count:
468 if plen != 0 and plen != 1 and (plen & (plen - 1)) == 0:
469 ShowRegistryEntryRecurse(Cast(ca.array[idx], 'IORegistryEntry *'), prefix + "| ", printProps)
470 else:
471 ShowRegistryEntryRecurse(Cast(ca.array[idx], 'IORegistryEntry *'), prefix + " ", printProps)
472 idx += 1
473
474 def FindRegistryEntryRecurse(entry, search_name, stopAfterFirst):
475 """ Checks if given registry entry's name matches the search_name we're looking for
476 If yes, it prints the entry's summary and then recurses through its children
477 If no, it does nothing and recurses through its children
478 """
479 # Setup
480 global plane
481 registryTable = entry.fRegistryTable
482 propertyTable = entry.fPropertyTable
483
484 # Compare
485 name = None
486 name = LookupKeyInOSDict(registryTable, kern.globals.gIOServicePlane.nameKey)
487 if name is None:
488 name = LookupKeyInOSDict(registryTable, kern.globals.gIONameKey)
489 if name is None:
490 name = LookupKeyInOSDict(propertyTable, kern.globals.gIOClassKey)
491
492 if name is not None:
493 if str(Cast(name, 'OSString *').string) == search_name:
494 print GetRegistryEntrySummary(entry)
495 if stopAfterFirst is True:
496 return True
497 elif Cast(entry, 'IOService *').pwrMgt and Cast(entry, 'IOService *').pwrMgt.Name:
498 name = Cast(entry, 'IOService *').pwrMgt.Name
499 if str(name) == search_name:
500 print GetRegistryEntrySummary(entry)
501 if stopAfterFirst is True:
502 return True
503
504 # Recurse
505 if plane is None:
506 childKey = kern.globals.gIOServicePlane.keys[1]
507 else:
508 childKey = plane.keys[1]
509 childArray = LookupKeyInOSDict(registryTable, childKey)
510 if childArray is not None:
511 idx = 0
512 ca = Cast(childArray, 'OSArray *')
513 count = unsigned(ca.count)
514 while idx < count:
515 if FindRegistryEntryRecurse(Cast(ca.array[idx], 'IORegistryEntry *'), search_name, stopAfterFirst) is True:
516 return True
517 idx += 1
518 return False
519
520 def FindRegistryObjectRecurse(entry, search_name):
521 """ Checks if given registry entry's name matches the search_name we're looking for
522 If yes, return the entry
523 If no, it does nothing and recurses through its children
524 Implicitly stops after finding the first entry
525 """
526 # Setup
527 global plane
528 registryTable = entry.fRegistryTable
529 propertyTable = entry.fPropertyTable
530
531 # Compare
532 name = None
533 name = LookupKeyInOSDict(registryTable, kern.globals.gIOServicePlane.nameKey)
534 if name is None:
535 name = LookupKeyInOSDict(registryTable, kern.globals.gIONameKey)
536 if name is None:
537 name = LookupKeyInOSDict(propertyTable, kern.globals.gIOClassKey)
538
539 if name is not None:
540 if str(Cast(name, 'OSString *').string) == search_name:
541 return entry
542 elif Cast(entry, 'IOService *').pwrMgt and Cast(entry, 'IOService *').pwrMgt.Name:
543 name = Cast(entry, 'IOService *').pwrMgt.Name
544 if str(name) == search_name:
545 return entry
546
547 # Recurse
548 if plane is None:
549 childKey = kern.globals.gIOServicePlane.keys[1]
550 else:
551 childKey = plane.keys[1]
552 childArray = LookupKeyInOSDict(registryTable, childKey)
553 if childArray is not None:
554 ca = Cast(childArray, 'OSArray *')
555 for idx in range(ca.count):
556 registry_object = FindRegistryObjectRecurse(Cast(ca.array[idx], 'IORegistryEntry *'), search_name)
557 if not registry_object or int(registry_object) == int(0):
558 continue
559 else:
560 return registry_object
561 return None
562
563 def LookupKeyInOSDict(osdict, key):
564 """ Returns the value corresponding to a given key in a OSDictionary
565 Returns None if the key was not found
566 """
567 if not osdict:
568 return
569 count = unsigned(osdict.count)
570 result = None
571 idx = 0
572 while idx < count and result is None:
573 if key == osdict.dictionary[idx].key:
574 result = osdict.dictionary[idx].value
575 idx += 1
576 return result
577
578 def LookupKeyInPropTable(propertyTable, key_str):
579 """ Returns the value corresponding to a given key from a registry entry's property table
580 Returns None if the key was not found
581 The property that is being searched for is specified as a string in key_str
582 """
583 if not propertyTable:
584 return
585 count = unsigned(propertyTable.count)
586 result = None
587 idx = 0
588 while idx < count and result is None:
589 if key_str == str(propertyTable.dictionary[idx].key.string):
590 result = propertyTable.dictionary[idx].value
591 idx += 1
592 return result
593
594 def GetRegDictionary(osdict, prefix):
595 """ Returns a specially formatted string summary of the given OSDictionary
596 This is done in order to pretty-print registry property tables in showregistry
597 and other macros
598 """
599 out_string = prefix + "{\n"
600 idx = 0
601 count = unsigned(osdict.count)
602
603 while idx < count:
604 out_string += prefix + " " + GetObjectSummary(osdict.dictionary[idx].key) + " = " + GetObjectSummary(osdict.dictionary[idx].value) + "\n"
605 idx += 1
606 out_string += prefix + "}\n"
607 return out_string
608
609 def GetString(string):
610 """ Returns the python string representation of a given OSString
611 """
612 out_string = "\"{0:s}\"".format(Cast(string, 'OSString *').string)
613 return out_string
614
615 def GetNumber(num):
616 out_string = "{0:d}".format(Cast(num, 'OSNumber *').value)
617 return out_string
618
619 def GetBoolean(b):
620 """ Shows info about a given OSBoolean
621 """
622 out_string = ""
623 if b == kern.globals.gOSBooleanFalse:
624 out_string += "No"
625 else:
626 out_string += "Yes"
627 return out_string
628
629 def GetMetaClass(mc):
630 """ Shows info about a given OSSymbol
631 """
632 out_string = "{0: <5d}x {1: >5d} bytes {2:s}\n".format(mc.instanceCount, mc.classSize, mc.className.string)
633 return out_string
634
635 def GetArray(arr):
636 """ Returns a string containing info about a given OSArray
637 """
638 out_string = ""
639 idx = 0
640 count = unsigned(arr.count)
641
642 while idx < count:
643 obj = arr.array[idx]
644 idx += 1
645 out_string += GetObjectSummary(obj)
646 if idx < unsigned(arr.count):
647 out_string += ","
648 return out_string
649
650 def GetDictionary(d):
651 """ Returns a string containing info about a given OSDictionary
652 """
653 out_string = "{"
654 idx = 0
655 count = unsigned(d.count)
656
657 while idx < count:
658 obj = d.dictionary[idx].key
659 out_string += GetObjectSummary(obj) + "="
660 obj = d.dictionary[idx].value
661 idx += 1
662 out_string += GetObjectSummary(obj)
663 if idx < count:
664 out_string += ","
665 out_string += "}"
666 return out_string
667
668 def GetSet(se):
669 """ Returns a string containing info about a given OSSet
670 """
671 out_string += "[" + GetArray(se.members) + "]"
672 return out_string
673
674 def ReadIOPortInt(addr, numbytes, lcpu):
675 """ Prints results after reading a given ioport
676 """
677 result = 0xBAD10AD
678
679 if "kdp" != GetConnectionProtocol():
680 print "Target is not connected over kdp. Nothing to do here."
681 return
682
683 # Set up the manual KDP packet
684 input_address = unsigned(addressof(kern.globals.manual_pkt.input))
685 len_address = unsigned(addressof(kern.globals.manual_pkt.len))
686 data_address = unsigned(addressof(kern.globals.manual_pkt.data))
687 if not WriteInt32ToMemoryAddress(0, input_address):
688 print "0x{0: <4x}: 0x{1: <1x}".format(addr, result)
689 return
690
691 kdp_pkt_size = GetType('kdp_readioport_req_t').GetByteSize()
692 if not WriteInt32ToMemoryAddress(kdp_pkt_size, len_address):
693 print "0x{0: <4x}: 0x{1: <1x}".format(addr, result)
694 return
695
696 kgm_pkt = kern.GetValueFromAddress(data_address, 'kdp_readioport_req_t *')
697
698 header_value = GetKDPPacketHeaderInt(request=GetEnumValue('kdp_req_t::KDP_READIOPORT'), length = kdp_pkt_size)
699
700 if( WriteInt64ToMemoryAddress((header_value), int(addressof(kgm_pkt.hdr))) and
701 WriteInt16ToMemoryAddress(addr, int(addressof(kgm_pkt.address))) and
702 WriteInt32ToMemoryAddress(numbytes, int(addressof(kgm_pkt.nbytes))) and
703 WriteInt16ToMemoryAddress(lcpu, int(addressof(kgm_pkt.lcpu))) and
704 WriteInt32ToMemoryAddress(1, input_address)
705 ):
706
707 result_pkt = Cast(addressof(kern.globals.manual_pkt.data), 'kdp_readioport_reply_t *')
708
709 if(result_pkt.error == 0):
710 print "This macro is incomplete till <rdar://problem/12868059> is fixed"
711 # FIXME: Uncomment me when <rdar://problem/12868059> is fixed
712 #if numbytes == 1:
713 # result = dereference(Cast(result_pkt.data, 'uint8_t *'))
714 #elif numbytes == 2:
715 # result = dereference(Cast(result_pkt.data, 'uint16_t *'))
716 #elif numbytes == 4:
717 # result = dereference(cast(result_pkt.data, 'uint32_t *'))
718
719 print "0x{0: <4x}: 0x{1: <1x}".format(addr, result)
720
721 def WriteIOPortInt(addr, numbytes, value, lcpu):
722 """ Writes 'value' into ioport specified by 'addr'. Prints errors if it encounters any
723 """
724 if "kdp" != GetConnectionProtocol():
725 print "Target is not connected over kdp. Nothing to do here."
726 return
727
728 # Set up the manual KDP packet
729 input_address = unsigned(addressof(kern.globals.manual_pkt.input))
730 len_address = unsigned(addressof(kern.globals.manual_pkt.len))
731 data_address = unsigned(addressof(kern.globals.manual_pkt.data))
732 if not WriteInt32ToMemoryAddress(0, input_address):
733 print "error writing 0x{0: x} to port 0x{1: <4x}".format(value, addr)
734 return
735
736 kdp_pkt_size = GetType('kdp_writeioport_req_t').GetByteSize()
737 if not WriteInt32ToMemoryAddress(kdp_pkt_size, len_address):
738 print "error writing 0x{0: x} to port 0x{1: <4x}".format(value, addr)
739 return
740
741 kgm_pkt = kern.GetValueFromAddress(data_address, 'kdp_writeioport_req_t *')
742
743 header_value = GetKDPPacketHeaderInt(request=GetEnumValue('kdp_req_t::KDP_WRITEIOPORT'), length = kdp_pkt_size)
744
745 if( WriteInt64ToMemoryAddress((header_value), int(addressof(kgm_pkt.hdr))) and
746 WriteInt16ToMemoryAddress(addr, int(addressof(kgm_pkt.address))) and
747 WriteInt32ToMemoryAddress(numbytes, int(addressof(kgm_pkt.nbytes))) and
748 WriteInt16ToMemoryAddress(lcpu, int(addressof(kgm_pkt.lcpu)))
749 ):
750 print "This macro is incomplete till <rdar://problem/12868059> is fixed"
751 # FIXME: Uncomment me when <rdar://problem/12868059> is fixed
752 #if numbytes == 1:
753 # if not WriteInt8ToMemoryAddress(value, int(addressof(kgm_pkt.data))):
754 # print "error writing 0x{0: x} to port 0x{1: <4x}".format(value, addr)
755 #elif numbytes == 2:
756 # if not WriteInt16ToMemoryAddress(value, int(addressof(kgm_pkt.data))):
757 # print "error writing 0x{0: x} to port 0x{1: <4x}".format(value, addr)
758 #elif numbytes == 4:
759 # if not WriteInt32ToMemoryAddress(value, int(addressof(kgm_pkt.data))):
760 # print "error writing 0x{0: x} to port 0x{1: <4x}".format(value, addr)
761
762 if not WriteInt32ToMemoryAddress(1, input_address):
763 print "error writing 0x{0: x} to port 0x{1: <4x}".format(value, addr)
764 return
765
766 result_pkt = Cast(addressof(kern.globals.manual_pkt.data), 'kdp_writeioport_reply_t *')
767
768 # Done with the write
769 if(result_pkt.error == 0):
770 print "Writing 0x {0: x} to port {1: <4x} was successful".format(value, addr)
771 else:
772 print "error writing 0x{0: x} to port 0x{1: <4x}".format(value, addr)
773