]>
Commit | Line | Data |
---|---|---|
316670eb A |
1 | import lldb |
2 | import re | |
3 | import 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 | |
9 | def findGlobal(variable): | |
10 | return lldb.target.FindGlobalVariables(variable, 0).GetValueAtIndex(0) | |
11 | ||
12 | def findGlobalValue(variable): | |
13 | return findGlobal(variable).GetValue() | |
14 | ||
15 | def readMemberUnsigned(variable,member): | |
16 | return variable.GetChildMemberWithName(member).GetValueAsUnsigned(0) | |
17 | ||
18 | def readMemberSigned(variable,member): | |
19 | return variable.GetChildMemberWithName(member).GetValueAsSigned() | |
20 | ||
21 | def readMemberString(variable,member): | |
22 | return str(variable.GetChildMemberWithName(member).GetSummary()).strip('"') | |
23 | ||
24 | ||
25 | ||
26 | class 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 | |
88 | def 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 | |
94 | def showallkexts_summary(kext_summary_header, lldb_dict): | |
95 | return "\n" + _summarizeallkexts(kext_summary_header) | |
96 | ||
97 | # Internal function for walking kext summaries | |
98 | def _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 | |
107 | def memstats_command(debugger,args,result,lldb_dict): | |
108 | stream = Output() | |
109 | stream.setOptions(args.split()) | |
110 | memstats(stream) | |
111 | stream.done() | |
112 | ||
113 | def 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 | |
129 | def zprint_command(debugger,args,result,lldb_dict): | |
130 | stream = Output() | |
131 | stream.setOptions(args.split()) | |
132 | _zprint(stream) | |
133 | stream.done() | |
134 | ||
135 | def _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 | |
165 | def showioalloc_command(debugger,args,result,lldb_dict): | |
166 | stream = Output() | |
167 | stream.setOptions(args.split()) | |
168 | _showioalloc(stream) | |
169 | stream.done() | |
170 | ||
171 | def _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 |