5 ######################################
7 ######################################
10 #####################################
12 #####################################
13 def CastIOKitClass(obj
, target_type
):
14 """ Type cast an object to another IOKIT CPP class.
16 obj - core.value object representing some C construct in lldb
17 target_type - str : ex 'OSString *'
20 v
= Cast(obj
, target_type
)
21 v
.GetSBValue().SetPreferDynamicValue(lldb
.eNoDynamicValues
)
24 ######################################
26 ######################################
27 @lldb_type_summary(['OSObject *'])
29 def GetObjectSummary(obj
):
30 """ Show info about an OSObject - its vtable ptr and retain count, & more info for simple container classes.
35 vt
= dereference(Cast(obj
, 'uintptr_t *')) - 2 * sizeof('uintptr_t')
36 vtype
= kern
.SymbolicateFromAddress(vt
)
37 if hasattr(obj
, 'retainCount'):
38 retCount
= (obj
.retainCount
& 0xffff)
39 cntnrRetCount
= (retCount
>> 16)
40 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
)
43 out_string
= "`object 0x{0: <16x}, vt 0x{1: <16x} <{2:s}>` ".format(obj
, vt
, vtype
[0].GetName())
45 out_string
= "`object 0x{0: <16x}, vt 0x{1: <16x}` ".format(obj
, vt
)
47 ztvAddr
= kern
.GetLoadAddressForSymbol('_ZTV8OSString')
49 out_string
+= GetString(obj
)
52 ztvAddr
= kern
.GetLoadAddressForSymbol('_ZTV8OSSymbol')
54 out_string
+= GetString(obj
)
57 ztvAddr
= kern
.GetLoadAddressForSymbol('_ZTV8OSNumber')
59 out_string
+= GetNumber(obj
)
62 ztvAddr
= kern
.GetLoadAddressForSymbol('_ZTV9OSBoolean')
64 out_string
+= GetBoolean(obj
)
67 ztvAddr
= kern
.GetLoadAddressForSymbol('_ZTV7OSArray')
69 out_string
+= "(" + GetArray(CastIOKitClass(obj
, 'OSArray *')) + ")"
72 ztvAddr
= kern
.GetLoadAddressForSymbol('_ZTV5OSSet')
74 out_string
+= GetSet(CastIOKitClass(obj
, 'OSSet *'))
77 ztvAddr
= kern
.GetLoadAddressForSymbol('_ZTV12OSDictionary')
79 out_string
+= GetDictionary(CastIOKitClass(obj
, 'OSDictionary *'))
84 @lldb_type_summary(['IORegistryEntry *'])
86 def GetRegistryEntrySummary(entry
):
87 """ returns a string containing summary information about an IORegistry
88 object including it's registry id , vtable ptr and retain count
92 registryTable
= entry
.fRegistryTable
93 propertyTable
= entry
.fPropertyTable
95 name
= LookupKeyInOSDict(registryTable
, kern
.globals.gIOServicePlane
.nameKey
)
97 name
= LookupKeyInOSDict(registryTable
, kern
.globals.gIONameKey
)
99 name
= LookupKeyInOSDict(propertyTable
, kern
.globals.gIOClassKey
)
102 out_string
+= "+-o {0:s} ".format(GetString(CastIOKitClass(name
, 'OSString *')))
103 elif CastIOKitClass(entry
, 'IOService *').pwrMgt
and CastIOKitClass(entry
, 'IOService *').pwrMgt
.Name
:
104 out_string
+= "+-o {0:s} ".format(CastIOKitClass(entry
, 'IOService *').pwrMgt
.Name
)
106 out_string
+= "+-o ?? "
108 # I'm using uintptr_t for now to work around <rdar://problem/12749733> FindFirstType & Co. should allow you to make pointer types directly
109 vtableAddr
= dereference(Cast(entry
, 'uintptr_t *')) - 2 * sizeof('uintptr_t *')
110 vtype
= kern
.SymbolicateFromAddress(vtableAddr
)
111 if vtype
is None or len(vtype
) < 1:
112 out_string
+= "<object 0x{0: <16x}, id 0x{1:x}, vtable 0x{2: <16x}".format(entry
, entry
.reserved
.fRegistryEntryID
, vtableAddr
)
114 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())
116 ztvAddr
= kern
.GetLoadAddressForSymbol('_ZTV15IORegistryEntry')
117 if vtableAddr
!= ztvAddr
:
119 state
= CastIOKitClass(entry
, 'IOService *').__state
[0]
120 # kIOServiceRegisteredState
123 out_string
+= "registered, "
124 # kIOServiceMatchedState
127 out_string
+= "matched, "
128 #kIOServiceInactiveState
131 busyCount
= (CastIOKitClass(entry
, 'IOService *').__state
[1] & 0xff)
132 retCount
= (CastIOKitClass(entry
, 'IOService *').retainCount
& 0xffff)
133 out_string
+= "active, busy {0}, retain count {1}>".format(busyCount
, retCount
)
136 ######################################
138 ######################################
139 @lldb_command('showallclasses')
140 def ShowAllClasses(cmd_args
=None):
141 """ Show the instance counts and ivar size of all OSObject subclasses.
142 See ioclasscount man page for details
145 count
= unsigned(kern
.globals.sAllClassesDict
.count
)
148 meta
= CastIOKitClass(kern
.globals.sAllClassesDict
.dictionary
[idx
].value
, 'OSMetaClass *')
150 print GetMetaClass(meta
)
152 @lldb_command('showobject')
153 def ShowObject(cmd_args
=None):
154 """ Show info about an OSObject - its vtable ptr and retain count, & more info for simple container classes.
157 print "Please specify the address of the OSObject whose info you want to view. Type help showobject for help"
160 obj
= kern
.GetValueFromAddress(cmd_args
[0], 'OSObject *')
161 print GetObjectSummary(obj
)
163 @lldb_command('setregistryplane')
164 def SetRegistryPlane(cmd_args
=None):
165 """ Set the plane to be used for the IOKit registry macros
166 syntax: (lldb) setregistryplane 0 - will display all known planes
167 syntax: (lldb) setregistryplane 0xaddr - will set the registry plane to 0xaddr
168 syntax: (lldb) setregistryplane gIODTPlane - will set the registry plane to gIODTPlane
171 print "Please specify the name of the plane you want to use with the IOKit registry macros."
172 print SetRegistryPlane
.__doc
__
174 if cmd_args
[0] == "0":
175 print GetObjectSummary(kern
.globals.gIORegistryPlanes
)
178 plane
= kern
.GetValueFromAddress(cmd_args
[0], 'IORegistryPlane *')
181 @lldb_command('showregistryentry')
182 def ShowRegistryEntry(cmd_args
=None):
183 """ Show info about a registry entry; its properties and descendants in the current plane
184 syntax: (lldb) showregistryentry 0xaddr
185 syntax: (lldb) showregistryentry gIOPMRootDomain
188 print "Please specify the address of the registry entry whose info you want to view."
189 print ShowRegistryEntry
.__doc
__
192 entry
= kern
.GetValueFromAddress(cmd_args
[0], 'IORegistryEntry *')
193 ShowRegistryEntryRecurse(entry
, "", True)
195 @lldb_command('showregistry')
196 def ShowRegistry(cmd_args
=None):
197 """ Show info about all registry entries in the current plane
198 If prior to invoking this command no registry plane is specified
199 using 'setregistryplane', the command defaults to the IOService plane
201 ShowRegistryEntryRecurse(kern
.globals.gRegistryRoot
, "", False)
203 @lldb_command('showregistryprops')
204 def ShowRegistryProps(cmd_args
=None):
205 """ Show info about all registry entries in the current plane, and their properties
206 If prior to invoking this command no registry plane is specified
207 using 'setregistryplane', the command defaults to the IOService plane
209 ShowRegistryEntryRecurse(kern
.globals.gRegistryRoot
, "", True)
211 @lldb_command('findregistryentry')
212 def FindRegistryEntry(cmd_args
=None):
213 """ Search for registry entry that matches the given string
214 If prior to invoking this command no registry plane is specified
215 using 'setregistryplane', the command defaults to searching entries from the IOService plane
216 syntax: (lldb) findregistryentries AppleACPICPU - will find the first registry entry that matches AppleACPICPU
219 print "Please specify the name of the registry entry you want to find"
220 print FindRegistryEntry
.__doc
__
223 FindRegistryEntryRecurse(kern
.globals.gRegistryRoot
, cmd_args
[0], True)
225 @lldb_command('findregistryentries')
226 def FindRegistryEntries(cmd_args
=None):
227 """ Search for all registry entries that match the given string
228 If prior to invoking this command no registry plane is specified
229 using 'setregistryplane', the command defaults to searching entries from the IOService plane
230 syntax: (lldb) findregistryentries AppleACPICPU - will find all registry entries that match AppleACPICPU
233 print "Please specify the name of the registry entry/entries you want to find"
234 print FindRegistryEntries
.__doc
__
237 FindRegistryEntryRecurse(kern
.globals.gRegistryRoot
, cmd_args
[0], False)
239 @lldb_command('findregistryprop')
240 def FindRegistryProp(cmd_args
=None):
241 """ Given a registry entry, print out the contents for the property that matches
243 syntax: (lldb) findregistryprop 0xaddr IOSleepSupported
244 syntax: (lldb) findregistryprop gIOPMRootDomain IOSleepSupported
245 syntax: (lldb) findregistryprop gIOPMRootDomain "Supported Features"
247 if not cmd_args
or len(cmd_args
) < 2:
248 print "Please specify the address of a IORegistry entry and the property you're looking for"
249 print FindRegistryProp
.__doc
__
252 entry
= kern
.GetValueFromAddress(cmd_args
[0], 'IOService *')
253 propertyTable
= entry
.fPropertyTable
254 print GetObjectSummary(LookupKeyInPropTable(propertyTable
, cmd_args
[1]))
256 @lldb_command('readioport8')
257 def ReadIOPort8(cmd_args
=None):
258 """ Read value stored in the specified IO port. The CPU can be optionally
260 Prints 0xBAD10AD in case of a bad read
261 Syntax: (lldb) readioport8 <port> [lcpu (kernel's numbering convention)]
264 print "Please specify a port to read out of"
265 print ReadIOPort8
.__doc__
268 portAddr
= ArgumentStringToInt(cmd_args
[0])
269 if len(cmd_args
) >= 2:
270 lcpu
= ArgumentStringToInt(cmd_args
[1])
272 lcpu
= xnudefines
.lcpu_self
274 ReadIOPortInt(portAddr
, 1, lcpu
)
276 @lldb_command('readioport16')
277 def ReadIOPort8(cmd_args
=None):
278 """ Read value stored in the specified IO port. The CPU can be optionally
280 Prints 0xBAD10AD in case of a bad read
281 Syntax: (lldb) readioport16 <port> [lcpu (kernel's numbering convention)]
284 print "Please specify a port to read out of"
285 print ReadIOPort16
.__doc__
288 portAddr
= ArgumentStringToInt(cmd_args
[0])
289 if len(cmd_args
) >= 2:
290 lcpu
= ArgumentStringToInt(cmd_args
[1])
292 lcpu
= xnudefines
.lcpu_self
294 ReadIOPortInt(portAddr
, 2, lcpu
)
296 @lldb_command('readioport32')
297 def ReadIOPort8(cmd_args
=None):
298 """ Read value stored in the specified IO port. The CPU can be optionally
300 Prints 0xBAD10AD in case of a bad read
301 Syntax: (lldb) readioport32 <port> [lcpu (kernel's numbering convention)]
304 print "Please specify a port to read out of"
305 print ReadIOPort32
.__doc__
308 portAddr
= ArgumentStringToInt(cmd_args
[0])
309 if len(cmd_args
) >= 2:
310 lcpu
= ArgumentStringToInt(cmd_args
[1])
312 lcpu
= xnudefines
.lcpu_self
314 ReadIOPortInt(portAddr
, 4, lcpu
)
316 @lldb_command('writeioport8')
317 def WriteIOPort8(cmd_args
=None):
318 """ Write the value to the specified IO port. The size of the value is
319 determined by the name of the command. The CPU used can be optionally
321 Syntax: (lldb) writeioport8 <port> <value> [lcpu (kernel's numbering convention)]
323 if not cmd_args
or len(cmd_args
) < 2:
324 print "Please specify a port to write to, followed by the value you want to write"
325 print WriteIOPort8
.__doc__
328 portAddr
= ArgumentStringToInt(cmd_args
[0])
329 value
= ArgumentStringToInt(cmd_args
[1])
331 if len(cmd_args
) >= 3:
332 lcpu
= ArgumentStringToInt(cmd_args
[2])
334 lcpu
= xnudefines
.lcpu_self
336 WriteIOPortInt(portAddr
, 1, value
, lcpu
)
338 @lldb_command('writeioport16')
339 def WriteIOPort8(cmd_args
=None):
340 """ Write the value to the specified IO port. The size of the value is
341 determined by the name of the command. The CPU used can be optionally
343 Syntax: (lldb) writeioport16 <port> <value> [lcpu (kernel's numbering convention)]
345 if not cmd_args
or len(cmd_args
) < 2:
346 print "Please specify a port to write to, followed by the value you want to write"
347 print WriteIOPort16
.__doc__
350 portAddr
= ArgumentStringToInt(cmd_args
[0])
351 value
= ArgumentStringToInt(cmd_args
[1])
353 if len(cmd_args
) >= 3:
354 lcpu
= ArgumentStringToInt(cmd_args
[2])
356 lcpu
= xnudefines
.lcpu_self
358 WriteIOPortInt(portAddr
, 2, value
, lcpu
)
360 @lldb_command('writeioport32')
361 def WriteIOPort8(cmd_args
=None):
362 """ Write the value to the specified IO port. The size of the value is
363 determined by the name of the command. The CPU used can be optionally
365 Syntax: (lldb) writeioport32 <port> <value> [lcpu (kernel's numbering convention)]
367 if not cmd_args
or len(cmd_args
) < 2:
368 print "Please specify a port to write to, followed by the value you want to write"
369 print WriteIOPort32
.__doc__
372 portAddr
= ArgumentStringToInt(cmd_args
[0])
373 value
= ArgumentStringToInt(cmd_args
[1])
375 if len(cmd_args
) >= 3:
376 lcpu
= ArgumentStringToInt(cmd_args
[2])
378 lcpu
= xnudefines
.lcpu_self
380 WriteIOPortInt(portAddr
, 4, value
, lcpu
)
382 @lldb_command('showioservicepm')
383 def ShowIOServicePM(cmd_args
=None):
384 """ Routine to dump the IOServicePM object
385 Syntax: (lldb) showioservicepm <IOServicePM pointer>
388 print "Please enter the pointer to the IOServicePM object you'd like to introspect"
389 print ShowIOServicePM
.__doc
__
392 iopmpriv
= kern
.GetValueFromAddress(cmd_args
[0], 'IOServicePM *')
393 out_string
= "MachineState {0: <6d} (".format(iopmpriv
.MachineState
)
398 1: 'kIOPM_OurChangeTellClientsPowerDown',
399 2: 'kIOPM_OurChangeTellClientsPowerDown',
400 3: 'kIOPM_OurChangeNotifyInterestedDriversWillChange',
401 4: 'kIOPM_OurChangeSetPowerState',
402 5: 'kIOPM_OurChangeWaitForPowerSettle',
403 6: 'kIOPM_OurChangeNotifyInterestedDriversDidChange',
404 7: 'kIOPM_OurChangeTellCapabilityDidChange',
405 8: 'kIOPM_OurChangeFinish',
406 9: 'Unused_MachineState_9',
407 10: 'kIOPM_ParentChangeTellPriorityClientsPowerDown',
408 11: 'kIOPM_ParentChangeNotifyInterestedDriversWillChange',
409 12: 'kIOPM_ParentChangeSetPowerState',
410 13: 'kIOPM_ParentChangeWaitForPowerSettle',
411 14: 'kIOPM_ParentChangeNotifyInterestedDriversDidChange',
412 15: 'kIOPM_ParentChangeTellCapabilityDidChange',
413 16: 'kIOPM_ParentChangeAcknowledgePowerChange',
414 17: 'kIOPM_NotifyChildrenStart',
415 18: 'kIOPM_NotifyChildrenOrdered',
416 19: 'kIOPM_NotifyChildrenDelayed',
417 20: 'kIOPM_SyncTellClientsPowerDown',
418 21: 'kIOPM_SyncTellPriorityClientsPowerDown',
419 22: 'kIOPM_SyncNotifyWillChange',
420 23: 'kIOPM_SyncNotifyDidChange',
421 24: 'kIOPM_SyncTellCapabilityDidChange',
422 25: 'kIOPM_SyncFinish',
423 26: 'kIOPM_TellCapabilityChangeDone',
424 27: 'kIOPM_DriverThreadCallDone'
426 powerstate
= unsigned(iopmpriv
.MachineState
)
427 if powerstate
in pstate_map
:
428 out_string
+= "{0:s}".format(pstate_map
[powerstate
])
430 out_string
+= "Unknown_MachineState"
433 if iopmpriv
.MachineState
!= 20:
434 out_string
+= "DriverTimer = {0: <6d}, SettleTime = {1: < 6d}, HeadNoteFlags = {2: #12x}, HeadNotePendingAcks = {3: #012x}, ".format(
435 unsigned(iopmpriv
.DriverTimer
),
436 unsigned(iopmpriv
.SettleTimeUS
),
437 unsigned(iopmpriv
.HeadNoteChangeFlags
),
438 unsigned(iopmpriv
.HeadNotePendingAcks
))
440 if iopmpriv
.DeviceOverrideEnabled
!= 0:
441 out_string
+= "DeviceOverrides, "
443 out_string
+= "DeviceDesire = {0: <6d}, DesiredPowerState = {1: <6d}, PreviousRequest = {2: <6d}\n".format(
444 unsigned(iopmpriv
.DeviceDesire
),
445 unsigned(iopmpriv
.DesiredPowerState
),
446 unsigned(iopmpriv
.PreviousRequestPowerFlags
))
450 ######################################
452 ######################################
453 def ShowRegistryEntryRecurse(entry
, prefix
, printProps
):
454 """ prints registry entry summary and recurses through all its children.
459 plen
= (len(prefix
)//2)
460 registryTable
= entry
.fRegistryTable
461 propertyTable
= entry
.fPropertyTable
463 # Print entry details
464 print "{0:s}{1:s}".format(prefix
, GetRegistryEntrySummary(entry
))
465 # Printing large property tables make it look like lldb is 'stuck'
467 print GetRegDictionary(propertyTable
, prefix
+ " | ")
471 childKey
= kern
.globals.gIOServicePlane
.keys
[1]
473 childKey
= plane
.keys
[1]
474 childArray
= LookupKeyInOSDict(registryTable
, childKey
)
475 if childArray
is not None:
477 ca
= CastIOKitClass(childArray
, 'OSArray *')
478 count
= unsigned(ca
.count
)
480 if plen
!= 0 and plen
!= 1 and (plen
& (plen
- 1)) == 0:
481 ShowRegistryEntryRecurse(CastIOKitClass(ca
.array
[idx
], 'IORegistryEntry *'), prefix
+ "| ", printProps
)
483 ShowRegistryEntryRecurse(CastIOKitClass(ca
.array
[idx
], 'IORegistryEntry *'), prefix
+ " ", printProps
)
486 def FindRegistryEntryRecurse(entry
, search_name
, stopAfterFirst
):
487 """ Checks if given registry entry's name matches the search_name we're looking for
488 If yes, it prints the entry's summary and then recurses through its children
489 If no, it does nothing and recurses through its children
493 registryTable
= entry
.fRegistryTable
494 propertyTable
= entry
.fPropertyTable
498 name
= LookupKeyInOSDict(registryTable
, kern
.globals.gIOServicePlane
.nameKey
)
500 name
= LookupKeyInOSDict(registryTable
, kern
.globals.gIONameKey
)
502 name
= LookupKeyInOSDict(propertyTable
, kern
.globals.gIOClassKey
)
505 if str(CastIOKitClass(name
, 'OSString *').string
) == search_name
:
506 print GetRegistryEntrySummary(entry
)
507 if stopAfterFirst
is True:
509 elif CastIOKitClass(entry
, 'IOService *').pwrMgt
and CastIOKitClass(entry
, 'IOService *').pwrMgt
.Name
:
510 name
= CastIOKitClass(entry
, 'IOService *').pwrMgt
.Name
511 if str(name
) == search_name
:
512 print GetRegistryEntrySummary(entry
)
513 if stopAfterFirst
is True:
518 childKey
= kern
.globals.gIOServicePlane
.keys
[1]
520 childKey
= plane
.keys
[1]
521 childArray
= LookupKeyInOSDict(registryTable
, childKey
)
522 if childArray
is not None:
524 ca
= CastIOKitClass(childArray
, 'OSArray *')
525 count
= unsigned(ca
.count
)
527 if FindRegistryEntryRecurse(CastIOKitClass(ca
.array
[idx
], 'IORegistryEntry *'), search_name
, stopAfterFirst
) is True:
532 def FindRegistryObjectRecurse(entry
, search_name
):
533 """ Checks if given registry entry's name matches the search_name we're looking for
534 If yes, return the entry
535 If no, it does nothing and recurses through its children
536 Implicitly stops after finding the first entry
540 registryTable
= entry
.fRegistryTable
541 propertyTable
= entry
.fPropertyTable
545 name
= LookupKeyInOSDict(registryTable
, kern
.globals.gIOServicePlane
.nameKey
)
547 name
= LookupKeyInOSDict(registryTable
, kern
.globals.gIONameKey
)
549 name
= LookupKeyInOSDict(propertyTable
, kern
.globals.gIOClassKey
)
552 if str(CastIOKitClass(name
, 'OSString *').string
) == search_name
:
554 elif CastIOKitClass(entry
, 'IOService *').pwrMgt
and CastIOKitClass(entry
, 'IOService *').pwrMgt
.Name
:
555 name
= CastIOKitClass(entry
, 'IOService *').pwrMgt
.Name
556 if str(name
) == search_name
:
561 childKey
= kern
.globals.gIOServicePlane
.keys
[1]
563 childKey
= plane
.keys
[1]
564 childArray
= LookupKeyInOSDict(registryTable
, childKey
)
565 if childArray
is not None:
566 ca
= CastIOKitClass(childArray
, 'OSArray *')
567 for idx
in range(ca
.count
):
568 registry_object
= FindRegistryObjectRecurse(CastIOKitClass(ca
.array
[idx
], 'IORegistryEntry *'), search_name
)
569 if not registry_object
or int(registry_object
) == int(0):
572 return registry_object
575 def LookupKeyInOSDict(osdict
, key
):
576 """ Returns the value corresponding to a given key in a OSDictionary
577 Returns None if the key was not found
581 count
= unsigned(osdict
.count
)
584 while idx
< count
and result
is None:
585 if key
== osdict
.dictionary
[idx
].key
:
586 result
= osdict
.dictionary
[idx
].value
590 def LookupKeyInPropTable(propertyTable
, key_str
):
591 """ Returns the value corresponding to a given key from a registry entry's property table
592 Returns None if the key was not found
593 The property that is being searched for is specified as a string in key_str
595 if not propertyTable
:
597 count
= unsigned(propertyTable
.count
)
600 while idx
< count
and result
is None:
601 if key_str
== str(propertyTable
.dictionary
[idx
].key
.string
):
602 result
= propertyTable
.dictionary
[idx
].value
606 def GetRegDictionary(osdict
, prefix
):
607 """ Returns a specially formatted string summary of the given OSDictionary
608 This is done in order to pretty-print registry property tables in showregistry
611 out_string
= prefix
+ "{\n"
613 count
= unsigned(osdict
.count
)
616 out_string
+= prefix
+ " " + GetObjectSummary(osdict
.dictionary
[idx
].key
) + " = " + GetObjectSummary(osdict
.dictionary
[idx
].value
) + "\n"
618 out_string
+= prefix
+ "}\n"
621 def GetString(string
):
622 """ Returns the python string representation of a given OSString
624 out_string
= "\"{0:s}\"".format(CastIOKitClass(string
, 'OSString *').string
)
628 out_string
= "{0:d}".format(CastIOKitClass(num
, 'OSNumber *').value
)
632 """ Shows info about a given OSBoolean
635 if b
== kern
.globals.gOSBooleanFalse
:
641 def GetMetaClass(mc
):
642 """ Shows info about a given OSSymbol
644 out_string
= "{0: <5d}x {1: >5d} bytes {2:s}\n".format(mc
.instanceCount
, mc
.classSize
, mc
.className
.string
)
648 """ Returns a string containing info about a given OSArray
652 count
= unsigned(arr
.count
)
657 out_string
+= GetObjectSummary(obj
)
658 if idx
< unsigned(arr
.count
):
662 def GetDictionary(d
):
663 """ Returns a string containing info about a given OSDictionary
667 count
= unsigned(d
.count
)
670 obj
= d
.dictionary
[idx
].key
671 out_string
+= GetObjectSummary(obj
) + "="
672 obj
= d
.dictionary
[idx
].value
674 out_string
+= GetObjectSummary(obj
)
681 """ Returns a string containing info about a given OSSet
683 out_string
+= "[" + GetArray(se
.members
) + "]"
686 def ReadIOPortInt(addr
, numbytes
, lcpu
):
687 """ Prints results after reading a given ioport
691 if "kdp" != GetConnectionProtocol():
692 print "Target is not connected over kdp. Nothing to do here."
695 # Set up the manual KDP packet
696 input_address
= unsigned(addressof(kern
.globals.manual_pkt
.input))
697 len_address
= unsigned(addressof(kern
.globals.manual_pkt
.len))
698 data_address
= unsigned(addressof(kern
.globals.manual_pkt
.data
))
699 if not WriteInt32ToMemoryAddress(0, input_address
):
700 print "0x{0: <4x}: 0x{1: <1x}".format(addr
, result
)
703 kdp_pkt_size
= GetType('kdp_readioport_req_t').GetByteSize()
704 if not WriteInt32ToMemoryAddress(kdp_pkt_size
, len_address
):
705 print "0x{0: <4x}: 0x{1: <1x}".format(addr
, result
)
708 kgm_pkt
= kern
.GetValueFromAddress(data_address
, 'kdp_readioport_req_t *')
710 header_value
= GetKDPPacketHeaderInt(request
=GetEnumValue('kdp_req_t::KDP_READIOPORT'), length
= kdp_pkt_size
)
712 if( WriteInt64ToMemoryAddress((header_value
), int(addressof(kgm_pkt
.hdr
))) and
713 WriteInt16ToMemoryAddress(addr
, int(addressof(kgm_pkt
.address
))) and
714 WriteInt32ToMemoryAddress(numbytes
, int(addressof(kgm_pkt
.nbytes
))) and
715 WriteInt16ToMemoryAddress(lcpu
, int(addressof(kgm_pkt
.lcpu
))) and
716 WriteInt32ToMemoryAddress(1, input_address
)
719 result_pkt
= Cast(addressof(kern
.globals.manual_pkt
.data
), 'kdp_readioport_reply_t *')
721 if(result_pkt
.error
== 0):
722 print "This macro is incomplete till <rdar://problem/12868059> is fixed"
723 # FIXME: Uncomment me when <rdar://problem/12868059> is fixed
725 # result = dereference(Cast(result_pkt.data, 'uint8_t *'))
727 # result = dereference(Cast(result_pkt.data, 'uint16_t *'))
729 # result = dereference(cast(result_pkt.data, 'uint32_t *'))
731 print "0x{0: <4x}: 0x{1: <1x}".format(addr
, result
)
733 def WriteIOPortInt(addr
, numbytes
, value
, lcpu
):
734 """ Writes 'value' into ioport specified by 'addr'. Prints errors if it encounters any
736 if "kdp" != GetConnectionProtocol():
737 print "Target is not connected over kdp. Nothing to do here."
740 # Set up the manual KDP packet
741 input_address
= unsigned(addressof(kern
.globals.manual_pkt
.input))
742 len_address
= unsigned(addressof(kern
.globals.manual_pkt
.len))
743 data_address
= unsigned(addressof(kern
.globals.manual_pkt
.data
))
744 if not WriteInt32ToMemoryAddress(0, input_address
):
745 print "error writing 0x{0: x} to port 0x{1: <4x}".format(value
, addr
)
748 kdp_pkt_size
= GetType('kdp_writeioport_req_t').GetByteSize()
749 if not WriteInt32ToMemoryAddress(kdp_pkt_size
, len_address
):
750 print "error writing 0x{0: x} to port 0x{1: <4x}".format(value
, addr
)
753 kgm_pkt
= kern
.GetValueFromAddress(data_address
, 'kdp_writeioport_req_t *')
755 header_value
= GetKDPPacketHeaderInt(request
=GetEnumValue('kdp_req_t::KDP_WRITEIOPORT'), length
= kdp_pkt_size
)
757 if( WriteInt64ToMemoryAddress((header_value
), int(addressof(kgm_pkt
.hdr
))) and
758 WriteInt16ToMemoryAddress(addr
, int(addressof(kgm_pkt
.address
))) and
759 WriteInt32ToMemoryAddress(numbytes
, int(addressof(kgm_pkt
.nbytes
))) and
760 WriteInt16ToMemoryAddress(lcpu
, int(addressof(kgm_pkt
.lcpu
)))
762 print "This macro is incomplete till <rdar://problem/12868059> is fixed"
763 # FIXME: Uncomment me when <rdar://problem/12868059> is fixed
765 # if not WriteInt8ToMemoryAddress(value, int(addressof(kgm_pkt.data))):
766 # print "error writing 0x{0: x} to port 0x{1: <4x}".format(value, addr)
768 # if not WriteInt16ToMemoryAddress(value, int(addressof(kgm_pkt.data))):
769 # print "error writing 0x{0: x} to port 0x{1: <4x}".format(value, addr)
771 # if not WriteInt32ToMemoryAddress(value, int(addressof(kgm_pkt.data))):
772 # print "error writing 0x{0: x} to port 0x{1: <4x}".format(value, addr)
774 if not WriteInt32ToMemoryAddress(1, input_address
):
775 print "error writing 0x{0: x} to port 0x{1: <4x}".format(value
, addr
)
778 result_pkt
= Cast(addressof(kern
.globals.manual_pkt
.data
), 'kdp_writeioport_reply_t *')
780 # Done with the write
781 if(result_pkt
.error
== 0):
782 print "Writing 0x {0: x} to port {1: <4x} was successful".format(value
, addr
)
784 print "error writing 0x{0: x} to port 0x{1: <4x}".format(value
, addr
)
786 @lldb_command('showinterruptcounts')
787 def showinterruptcounts(cmd_args
=None):
788 """ Shows event source based interrupt counts by nub name and interrupt index.
789 Does not cover interrupts that are not event source based. Will report 0
790 if interrupt accounting is disabled.
793 header_format
= "{0: <20s} {1: >5s} {2: >20s}"
794 content_format
= "{0: <20s} {1: >5d} {2: >20d}"
796 print header_format
.format("Name", "Index", "Count")
798 for i
in kern
.interrupt_stats
:
799 owner
= CastIOKitClass(i
.owner
, 'IOInterruptEventSource *')
800 nub
= CastIOKitClass(owner
.provider
, 'IORegistryEntry *')
803 # To uniquely identify an interrupt, we need the nub name and the index. The index
804 # is stored with the stats object, but we need to retrieve the name.
806 registryTable
= nub
.fRegistryTable
807 propertyTable
= nub
.fPropertyTable
809 name
= LookupKeyInOSDict(registryTable
, kern
.globals.gIOServicePlane
.nameKey
)
811 name
= LookupKeyInOSDict(registryTable
, kern
.globals.gIONameKey
)
813 name
= LookupKeyInOSDict(propertyTable
, kern
.globals.gIOClassKey
)
818 nub_name
= GetString(CastIOKitClass(name
, 'OSString *'))
820 # We now have everything we need; spew the requested data.
822 interrupt_index
= i
.interruptIndex
823 first_level_count
= i
.interruptStatistics
[0]
825 print content_format
.format(nub_name
, interrupt_index
, first_level_count
)
829 @lldb_command('showinterruptstats')
830 def showinterruptstats(cmd_args
=None):
831 """ Shows event source based interrupt statistics by nub name and interrupt index.
832 Does not cover interrupts that are not event source based. Will report 0
833 if interrupt accounting is disabled, or if specific statistics are disabled.
834 Time is reported in ticks of mach_absolute_time. Statistics are:
836 Interrupt Count: Number of times the interrupt context handler was run
837 Interrupt Time: Total time spent in the interrupt context handler (if any)
838 Workloop Count: Number of times the kernel context handler was run
839 Workloop CPU Time: Total CPU time spent running the kernel context handler
840 Workloop Time: Total time spent running the kernel context handler
843 header_format
= "{0: <20s} {1: >5s} {2: >20s} {3: >20s} {4: >20s} {5: >20s} {6: >20s}"
844 content_format
= "{0: <20s} {1: >5d} {2: >20d} {3: >20d} {4: >20d} {5: >20d} {6: >20d}"
846 print header_format
.format("Name", "Index", "Interrupt Count", "Interrupt Time", "Workloop Count", "Workloop CPU Time", "Workloop Time")
848 for i
in kern
.interrupt_stats
:
849 owner
= CastIOKitClass(i
.owner
, 'IOInterruptEventSource *')
850 nub
= CastIOKitClass(owner
.provider
, 'IORegistryEntry *')
853 # To uniquely identify an interrupt, we need the nub name and the index. The index
854 # is stored with the stats object, but we need to retrieve the name.
856 registryTable
= nub
.fRegistryTable
857 propertyTable
= nub
.fPropertyTable
859 name
= LookupKeyInOSDict(registryTable
, kern
.globals.gIOServicePlane
.nameKey
)
861 name
= LookupKeyInOSDict(registryTable
, kern
.globals.gIONameKey
)
863 name
= LookupKeyInOSDict(propertyTable
, kern
.globals.gIOClassKey
)
868 nub_name
= GetString(CastIOKitClass(name
, 'OSString *'))
870 # We now have everything we need; spew the requested data.
872 interrupt_index
= i
.interruptIndex
873 first_level_count
= i
.interruptStatistics
[0]
874 second_level_count
= i
.interruptStatistics
[1]
875 first_level_time
= i
.interruptStatistics
[2]
876 second_level_cpu_time
= i
.interruptStatistics
[3]
877 second_level_system_time
= i
.interruptStatistics
[4]
879 print content_format
.format(nub_name
, interrupt_index
, first_level_count
, first_level_time
, second_level_count
, second_level_cpu_time
, second_level_system_time
)