]>
Commit | Line | Data |
---|---|---|
39037602 A |
1 | from xnu import * |
2 | from utils import * | |
3 | ||
4 | # From the defines in bsd/sys/kdebug.h: | |
5 | ||
6 | KdebugClassNames = { | |
7 | 1: "MACH", | |
8 | 2: "NETWORK", | |
9 | 3: "FSYSTEM", | |
10 | 4: "BSD", | |
11 | 5: "IOKIT", | |
12 | 6: "DRIVERS", | |
13 | 7: "TRACE", | |
14 | 8: "DLIL", | |
15 | 9: "WORKQUEUE", | |
16 | 10: "CORESTORAGE", | |
17 | 11: "CG", | |
18 | 20: "MISC", | |
19 | 30: "SECURITY", | |
20 | 31: "DYLD", | |
21 | 32: "QT", | |
22 | 33: "APPS", | |
23 | 34: "LAUNCHD", | |
24 | 36: "PPT", | |
25 | 37: "PERF", | |
26 | 38: "IMPORTANCE", | |
27 | 39: "PERFCTRL", | |
28 | 40: "BANK", | |
29 | 41: "XPC", | |
30 | 42: "ATM", | |
31 | 43: "ARIADNE", | |
32 | 44: "DAEMON", | |
33 | 45: "ENERGYTRACE", | |
34 | 49: "IMG", | |
35 | 50: "CLPC", | |
36 | 128: "ANS", | |
37 | 129: "SIO", | |
38 | 130: "SEP", | |
39 | 131: "ISP", | |
40 | 132: "OSCAR", | |
41 | 133: "EMBEDDEDGFX" | |
42 | } | |
43 | ||
44 | def GetKdebugClassName(class_num): | |
45 | return (KdebugClassNames[class_num] + ' ({})'.format(class_num) if class_num in KdebugClassNames else 'unknown ({})'.format(class_num)) | |
46 | ||
47 | @lldb_type_summary(['typefilter_t']) | |
48 | @header('{0: <20s}'.format("class") + ' '.join(map('{:02x}'.format, xrange(0, 255, 8)))) | |
49 | def GetKdebugTypefilter(typefilter): | |
50 | """ Summarizes the provided typefilter. | |
51 | """ | |
52 | classes = 256 | |
53 | subclasses_per_class = 256 | |
54 | ||
55 | # 8 bits at a time | |
56 | subclasses_per_element = 64 | |
57 | cur_typefilter = cast(typefilter, 'uint64_t *') | |
58 | subclasses_fmts = ' '.join(['{:02x}'] * 8) | |
59 | ||
60 | elements_per_class = subclasses_per_class / subclasses_per_element | |
61 | ||
62 | out_str = '' | |
63 | for i in xrange(0, classes): | |
64 | print_class = False | |
65 | subclasses = [0] * elements_per_class | |
66 | ||
67 | # check subclass ranges for set bits, remember those subclasses | |
68 | for j in xrange(0, elements_per_class): | |
69 | element = unsigned(cur_typefilter[i * elements_per_class + j]) | |
70 | if element != 0: | |
71 | print_class = True | |
72 | if print_class: | |
73 | subclasses[j] = element | |
74 | ||
5ba3f43e | 75 | ## if any of the bits were set in a class, print the entire class |
39037602 A |
76 | if print_class: |
77 | out_str += '{:<20s}'.format(GetKdebugClassName(i)) | |
78 | for element in subclasses: | |
79 | # split up the 64-bit values into byte-sized pieces | |
80 | bytes = [unsigned((element >> i) & 0xff) for i in (0, 8, 16, 24, 32, 40, 48, 56)] | |
81 | out_str += subclasses_fmts.format(*bytes) | |
82 | out_str += ' ' | |
83 | ||
84 | out_str += '\n' | |
85 | ||
86 | return out_str | |
87 | ||
88 | @lldb_command('showkdebugtypefilter') | |
89 | def ShowKdebugTypefilter(cmd_args=None): | |
90 | """ Show the current kdebug typefilter (or the typefilter at an address) | |
91 | ||
92 | usage: showkdebugtypefilter [<address>] | |
93 | """ | |
94 | ||
95 | if cmd_args: | |
39037602 A |
96 | typefilter = kern.GetValueFromAddress(cmd_args[0], 'typefilter_t') |
97 | if unsigned(typefilter) == 0: | |
98 | raise ArgumentError('argument provided is NULL') | |
99 | ||
813fb2f6 A |
100 | print GetKdebugTypefilter.header |
101 | print '-' * len(GetKdebugTypefilter.header) | |
102 | ||
103 | print GetKdebugTypefilter(typefilter) | |
39037602 A |
104 | return |
105 | ||
106 | typefilter = kern.globals.kdbg_typefilter | |
107 | if unsigned(typefilter) == 0: | |
108 | raise ArgumentError('no argument provided and active typefilter is not set') | |
109 | ||
110 | print GetKdebugTypefilter.header | |
111 | print '-' * len(GetKdebugTypefilter.header) | |
112 | print GetKdebugTypefilter(typefilter) | |
813fb2f6 A |
113 | |
114 | def GetKdebugStatus(): | |
115 | """ Get a string summary of the kdebug subsystem. | |
116 | """ | |
117 | out = '' | |
118 | ||
119 | kdebug_flags = kern.globals.kd_ctrl_page.kdebug_flags | |
120 | out += 'kdebug flags: {}\n'.format(xnudefines.GetStateString(xnudefines.kdebug_flags_strings, kdebug_flags)) | |
121 | events = kern.globals.nkdbufs | |
5ba3f43e | 122 | buf_mb = events * (64 if kern.arch == 'x86_64' or kern.arch.startswith('arm64') else 32) / 1000000 |
813fb2f6 A |
123 | out += 'events allocated: {:<d} ({:<d} MB)\n'.format(events, buf_mb) |
124 | out += 'enabled: {}\n'.format('yes' if kern.globals.kdebug_enable != 0 else 'no') | |
125 | if kdebug_flags & xnudefines.kdebug_typefilter_check: | |
126 | out += 'typefilter:\n' | |
127 | out += GetKdebugTypefilter.header + '\n' | |
128 | out += '-' * len(GetKdebugTypefilter.header) + '\n' | |
129 | typefilter = kern.globals.kdbg_typefilter | |
130 | if unsigned(typefilter) != 0: | |
131 | out += GetKdebugTypefilter(typefilter) | |
132 | ||
133 | return out | |
134 | ||
135 | @lldb_command('showkdebug') | |
136 | def ShowKdebug(cmd_args=None): | |
137 | """ Show the current kdebug state. | |
138 | ||
139 | usage: showkdebug | |
140 | """ | |
141 | ||
5ba3f43e | 142 | print GetKdebugStatus() |
813fb2f6 A |
143 | |
144 | @lldb_type_summary(['kperf_timer']) | |
145 | @header('{:<10s} {:<7s} {:<20s}'.format('period-ns', 'action', 'pending')) | |
146 | def GetKperfTimerSummary(timer): | |
147 | """ Get a string summary of a kperf timer. | |
148 | ||
149 | params: | |
150 | timer: the kperf_timer object to get a summary of | |
151 | """ | |
152 | return '{:<10d} {:<7d} {:<20x}\n'.format( | |
153 | kern.GetNanotimeFromAbstime(timer.period), timer.actionid, timer.pending_cpus) | |
154 | ||
155 | @lldb_type_summary(['action']) | |
156 | @header('{:<10s} {:<20s} {:<20s}'.format('pid-filter', 'user-data', 'samplers')) | |
157 | def GetKperfActionSummary(action): | |
158 | """ Get a string summary of a kperf action. | |
159 | ||
160 | params: | |
161 | action: the action object to get a summary of | |
162 | """ | |
163 | samplers = xnudefines.GetStateString(xnudefines.kperf_samplers_strings, action.sample) | |
164 | return '{:<10s} {:<20x} {:<20s}\n'.format( | |
165 | '-' if action.pid_filter < 0 else str(action.pid_filter), action.userdata, samplers) | |
166 | ||
167 | def GetKperfStatus(): | |
168 | """ Get a string summary of the kperf subsystem. | |
169 | """ | |
170 | out = '' | |
171 | ||
172 | kperf_status = kern.globals.sampling_status | |
173 | out += 'sampling: ' | |
174 | if kperf_status == 0: | |
175 | out += 'off\n' | |
176 | elif kperf_status == 1: | |
177 | out += 'on\n' | |
178 | elif kperf_status == 2: | |
179 | out += 'shutting down\n' | |
180 | else: | |
181 | out += 'unknown\n' | |
182 | ||
183 | pet = 0# kern.globals.pet_running | |
184 | pet_timer_id = kern.globals.pet_timer_id | |
185 | if pet != 0: | |
186 | pet_idle_rate = kern.globals.pet_idle_rate | |
187 | out += 'legacy PET is active (timer = {:<d}, idle rate = {:<d})\n'.format(pet_timer_id, pet_idle_rate) | |
188 | else: | |
189 | out += 'legacy PET is off\n' | |
190 | ||
191 | lw_pet = kern.globals.kperf_lightweight_pet_active | |
192 | if lw_pet != 0: | |
193 | lw_pet_gen = kern.globals.kperf_pet_gen | |
194 | out += 'lightweight PET is active (timer = {:<d}, generation count = {:<d})\n'.format(pet_timer_id, lw_pet_gen) | |
195 | else: | |
196 | out += 'lightweight PET is off\n' | |
197 | ||
198 | actions = kern.globals.actionc | |
199 | actions_arr = kern.globals.actionv | |
200 | ||
201 | out += 'actions:\n' | |
202 | out += '{:<5s} '.format('id') + GetKperfActionSummary.header + '\n' | |
203 | for i in xrange(0, actions): | |
204 | out += '{:<5d} '.format(i) + GetKperfActionSummary(actions_arr[i]) | |
205 | ||
206 | timers = kern.globals.kperf_timerc | |
207 | timers_arr = kern.globals.kperf_timerv | |
208 | ||
209 | out += 'timers:\n' | |
210 | out += '{:<5s} '.format('id') + GetKperfTimerSummary.header + '\n' | |
211 | for i in xrange(0, timers): | |
212 | out += '{:<5d} '.format(i) + GetKperfTimerSummary(timers_arr[i]) | |
213 | ||
214 | return out | |
215 | ||
216 | def GetKtraceStatus(): | |
217 | """ Get a string summary of the ktrace subsystem. | |
218 | """ | |
219 | out = '' | |
220 | ||
221 | state = kern.globals.ktrace_state | |
222 | if state == GetEnumValue('ktrace_state::KTRACE_STATE_OFF'): | |
223 | out += 'ktrace is off\n' | |
224 | else: | |
225 | out += 'ktrace is active (' | |
226 | if state == GetEnumValue('ktrace_state::KTRACE_STATE_FG'): | |
227 | out += 'foreground)' | |
228 | else: | |
229 | out += 'background)' | |
230 | out += '\n' | |
231 | owner = kern.globals.ktrace_last_owner_execname | |
232 | out += 'owned by: {0: <s}\n'.format(owner) | |
233 | active_mask = kern.globals.ktrace_active_mask | |
234 | out += 'active systems: {:<#x}\n'.format(active_mask) | |
235 | ||
236 | return out | |
237 | ||
238 | @lldb_command('showktrace') | |
239 | def ShowKtrace(cmd_args=None): | |
240 | """ Show the current ktrace state, including subsystems. | |
241 | ||
242 | usage: showktrace | |
243 | """ | |
244 | ||
245 | print GetKtraceStatus() | |
246 | print ' ' | |
247 | print 'kdebug:' | |
248 | print GetKdebugStatus() | |
249 | print ' ' | |
250 | print 'kperf:' | |
251 | print GetKperfStatus() |