1import lldb 2import re 3import getopt 4 5# Note: This module will eventually contain loads of macros. So please bear with the Macro/EndMacro comments 6 7 8# Global functions 9def findGlobal(variable): 10 return lldb.target.FindGlobalVariables(variable, 0).GetValueAtIndex(0) 11 12def findGlobalValue(variable): 13 return findGlobal(variable).GetValue() 14 15def readMemberUnsigned(variable,member): 16 return variable.GetChildMemberWithName(member).GetValueAsUnsigned(0) 17 18def readMemberSigned(variable,member): 19 return variable.GetChildMemberWithName(member).GetValueAsSigned() 20 21def readMemberString(variable,member): 22 return str(variable.GetChildMemberWithName(member).GetSummary()).strip('"') 23 24 25 26class Output : 27 """ 28 An output handler for all command. Use Output.print to direct all output of macro via the handler. 29 Currently this provide capabilities 30 -o path/to/filename 31 The output of this command execution will be saved to file. Parser information or errors will 32 not be sent to file though. eg /tmp/output.txt 33 -s filter_string 34 the "filter_string" param is parsed to python regex expression and each line of output 35 will be printed/saved only if it matches the expression. 36 The command header will not be filtered in any case. 37 """ 38 STDOUT =1 39 FILEOUT =2 40 FILTER =False 41 42 def __init__(self): 43 self.out = Output.STDOUT 44 self.fname=None 45 self.fhandle=None 46 self.FILTER=False 47 48 def printString(self, s): 49 """ Handler for all commands output. By default just print to stdout """ 50 if self.FILTER and not self.reg.search(s): return 51 if self.out == Output.STDOUT: print s 52 elif self.out == Output.FILEOUT : self.fhandle.write(s+"\n") 53 54 def printHeader(self,s): 55 if self.out == Output.STDOUT: print s 56 elif self.out == Output.FILEOUT: self.fhandle.write(s+"\n") 57 58 def done(self): 59 """ closes any open files. report on any errors """ 60 if self.fhandle != None : 61 self.fhandle.close() 62 63 def setOptions(self,args): 64 """ parse the arguments passed to the command 65 param : args => [] of <str> (typically args.split()) 66 """ 67 opts=() 68 try: 69 opts,args = getopt.getopt(args,'o:s:',[]) 70 except getopt.GetoptError,err: 71 print str(err) 72 #continue with processing 73 for o,a in opts : 74 if o == "-o" and len(a) > 0: 75 self.fname=a.strip() 76 self.fhandle=open(self.fname,"w") 77 self.out = Output.FILEOUT 78 print "saving results in file ",str(a) 79 elif o == "-s" and len(a) > 0: 80 self.reg = re.compile(a.strip(),re.MULTILINE|re.DOTALL) 81 self.FILTER=True 82 print "showing results for regex:",a.strip() 83 else : 84 print "Error: unknown option ",o,a 85 86 87# Inteface function for showallkexts command 88def showallkexts_command(debugger, args, result, lldb_dict): 89 kext_summary_header = findGlobal("gLoadedKextSummaries") 90 result.Printf(_summarizeallkexts(kext_summary_header)) 91 return None 92 93# Interface function for loaded kext summary formatter 94def showallkexts_summary(kext_summary_header, lldb_dict): 95 return "\n" + _summarizeallkexts(kext_summary_header) 96 97# Internal function for walking kext summaries 98def _summarizeallkexts(kext_summary_header): 99 summary = "ID Address Size Version Name\n" 100 summaries = kext_summary_header.GetChildMemberWithName("summaries") 101 count = int(kext_summary_header.GetChildMemberWithName("numSummaries").GetValue()) 102 for i in range(0, count): 103 summary += summaries.GetChildAtIndex(i, lldb.eNoDynamicValues, True).GetSummary() + "\n" 104 return summary 105 106# Macro: memstats 107def memstats_command(debugger,args,result,lldb_dict): 108 stream = Output() 109 stream.setOptions(args.split()) 110 memstats(stream) 111 stream.done() 112 113def memstats(ostream): 114 ostream.printString ( "kern_memorystatus_level: {0}".format(findGlobalValue("kern_memorystatus_level")) ) 115 ostream.printString ( "vm_page_throttled_count: {0}".format(findGlobalValue("vm_page_throttled_count")) ) 116 ostream.printString ( "vm_page_active_count: {0}".format(findGlobalValue("vm_page_active_count")) ) 117 ostream.printString ( "vm_page_inactive_count: {0}".format(findGlobalValue("vm_page_inactive_count")) ) 118 ostream.printString ( "vm_page_wire_count: {0}".format(findGlobalValue("vm_page_wire_count")) ) 119 ostream.printString ( "vm_page_free_count: {0}".format(findGlobalValue("vm_page_free_count")) ) 120 ostream.printString ( "vm_page_purgeable_count: {0}".format(findGlobalValue("vm_page_purgeable_count")) ) 121 ostream.printString ( "vm_page_inactive_target: {0}".format(findGlobalValue("vm_page_inactive_target")) ) 122 ostream.printString ( "vm_page_free_target: {0}".format(findGlobalValue("vm_page_free_target")) ) 123 ostream.printString ( "insue_ptepages_count: {0}".format(findGlobalValue("inuse_ptepages_count")) ) 124 ostream.printString ( "vm_page_free_reserved: {0}".format(findGlobalValue("vm_page_free_reserved")) ) 125# EndMacro: memstats 126 127 128# Macro: zprint 129def zprint_command(debugger,args,result,lldb_dict): 130 stream = Output() 131 stream.setOptions(args.split()) 132 _zprint(stream) 133 stream.done() 134 135def _zprint(ostream): 136 """Display info about memory zones""" 137 ostream.printHeader ( "{0: ^20s} {1: >5s} {2: >12s} {3: >12s} {4: >7s} {5: >8s} {6: >9s} {7: >8s} {8: <20s} {9} ".format('ZONE', 'COUNT', 'TOT_SZ', 'MAX_SZ', 'ELT_SZ', 'ALLOC_SZ', 'TOT_ALLOC', 'TOT_FREE', 'NAME','') ) 138 format_string = '{0: >#020x} {1: >5d} {2: >12d} {3: >12d} {4: >7d} {5: >8d} {6: >9d} {7: >8d} {8: <20s} {9}' 139 zone_ptr = findGlobal("first_zone"); 140 141 while zone_ptr.GetValueAsUnsigned() != 0 : 142 addr = zone_ptr.GetValueAsUnsigned() 143 count = readMemberUnsigned(zone_ptr, "count") 144 cur_size = readMemberUnsigned(zone_ptr, "cur_size") 145 max_size = readMemberUnsigned(zone_ptr, "max_size") 146 elem_size = readMemberUnsigned(zone_ptr, "elem_size") 147 alloc_size = readMemberUnsigned(zone_ptr, "alloc_size") 148 num_allocs = readMemberUnsigned(zone_ptr, "num_allocs") 149 num_frees = readMemberUnsigned(zone_ptr, "num_frees") 150 name = str(readMemberString(zone_ptr, "zone_name")) 151 markings="" 152 if str(zone_ptr.GetChildMemberWithName("exhaustible").GetValue()) == '1' : markings+="H" 153 if str(zone_ptr.GetChildMemberWithName("collectable").GetValue()) == '1' : markings+="C" 154 if str(zone_ptr.GetChildMemberWithName("expandable").GetValue()) == '1' : markings+="X" 155 if str(zone_ptr.GetChildMemberWithName("noencrypt").GetValue()) == '1' : markings+="$" 156 157 ostream.printString(format_string.format(addr, count, cur_size, max_size, elem_size, alloc_size, num_allocs, num_frees, name, markings)) 158 159 zone_ptr = zone_ptr.GetChildMemberWithName("next_zone") 160 return None 161# EndMacro: zprint 162 163 164# Macro: showioalloc 165def showioalloc_command(debugger,args,result,lldb_dict): 166 stream = Output() 167 stream.setOptions(args.split()) 168 _showioalloc(stream) 169 stream.done() 170 171def _showioalloc(ostream): 172 ivars_size = findGlobal("debug_ivars_size").GetValueAsUnsigned() 173 container_malloc_size = findGlobal("debug_container_malloc_size").GetValueAsUnsigned() 174 iomalloc_size = findGlobal("debug_iomalloc_size").GetValueAsUnsigned() 175 iomallocpageable_size = findGlobal("debug_iomallocpageable_size").GetValueAsUnsigned() 176 177 ostream.printString("Instance allocation = {0:#0x} = {1:d} K".format(ivars_size, (int)(ivars_size/1024))) 178 ostream.printString("Container allocation = {0:#0x} = {1:d} K".format(container_malloc_size,(int)(container_malloc_size/1024))) 179 ostream.printString("IOMalloc allocation = {0:#0x} = {1:d} K".format(iomalloc_size,(int)(iomalloc_size/1024))) 180 ostream.printString("Pageable allocation = {0:#0x} = {1:d} K".format(iomallocpageable_size,(int)(iomallocpageable_size/1024))) 181 return None 182# EndMacro: showioalloc 183 184 185