1from xnu import * 2from utils import * 3import sys 4 5###################################### 6# Globals 7###################################### 8plane = None 9 10###################################### 11# Type Summaries 12###################################### 13@lldb_type_summary(['OSObject *']) 14@header("") 15def 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("") 72def 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') 128def 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') 141def 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') 152def 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') 170def 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') 184def 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') 192def 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') 200def 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') 214def 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') 228def 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') 245def 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') 265def 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') 285def 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') 305def 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') 327def 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') 349def 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') 371def 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###################################### 441def 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 474def 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 520def 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 563def 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 578def 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 594def 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 609def 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 615def GetNumber(num): 616 out_string = "{0:d}".format(Cast(num, 'OSNumber *').value) 617 return out_string 618 619def 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 629def 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 635def 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 650def 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 668def GetSet(se): 669 """ Returns a string containing info about a given OSSet 670 """ 671 out_string += "[" + GetArray(se.members) + "]" 672 return out_string 673 674def 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 721def 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 774