]>
Commit | Line | Data |
---|---|---|
1 | ||
2 | """ Please make sure you read the README COMPLETELY BEFORE reading anything below. | |
3 | It is very critical that you read coding guidelines in Section E in README file. | |
4 | """ | |
5 | ||
6 | from xnu import * | |
7 | from utils import * | |
8 | ||
9 | from mbufdefines import * | |
10 | import xnudefines | |
11 | ||
12 | # Macro: mbuf_stat | |
13 | @lldb_command('mbuf_stat') | |
14 | def MBufStat(cmd_args=None): | |
15 | """ Print extended mbuf allocator statistics. | |
16 | """ | |
17 | hdr_format = "{0: <16s} {1: >8s} {2: >8s} {3: ^16s} {4: >8s} {5: >12s} {6: >8s} {7: >8s} {8: >8s}" | |
18 | print hdr_format.format('class', 'total', 'cached', 'uncached', 'inuse', 'failed', 'waiter', 'notified', 'purge') | |
19 | print hdr_format.format('name', 'objs', 'objs', 'objs/slabs', 'objs', 'alloc count', 'count', 'count', 'count') | |
20 | print hdr_format.format('-'*16, '-'*8, '-'*8, '-'*16, '-'*8, '-'*12, '-'*8, '-'*8, '-'*8) | |
21 | entry_format = "{0: <16s} {1: >8d} {2: >8d} {3:>7d} / {4:<6d} {5: >8d} {6: >12d} {7: >8d} {8: >8d} {9: >8d}" | |
22 | num_items = sizeof(kern.globals.mbuf_table) / sizeof(kern.globals.mbuf_table[0]) | |
23 | ncpus = int(kern.globals.ncpu) | |
24 | for i in range(num_items): | |
25 | mbuf = kern.globals.mbuf_table[i] | |
26 | mcs = Cast(mbuf.mtbl_stats, 'mb_class_stat_t *') | |
27 | mc = mbuf.mtbl_cache | |
28 | total = 0 | |
29 | total += int(mc.mc_full.bl_total) * int(mc.mc_cpu[0].cc_bktsize) | |
30 | ccp_arr = mc.mc_cpu | |
31 | for i in range(ncpus): | |
32 | ccp = ccp_arr[i] | |
33 | if int(ccp.cc_objs) > 0: | |
34 | total += int(ccp.cc_objs) | |
35 | if int(ccp.cc_pobjs) > 0: | |
36 | total += int(ccp.cc_pobjs) | |
37 | print entry_format.format(mcs.mbcl_cname, mcs.mbcl_total, total, | |
38 | mcs.mbcl_infree, mcs.mbcl_slab_cnt, | |
39 | (mcs.mbcl_total - total - mcs.mbcl_infree), | |
40 | mcs.mbcl_fail_cnt, mbuf.mtbl_cache.mc_waiter_cnt, | |
41 | mcs.mbcl_notified, mcs.mbcl_purge_cnt | |
42 | ) | |
43 | # EndMacro: mbuf_stat | |
44 | ||
45 | # Macro: mbuf_walkpkt | |
46 | @lldb_command('mbuf_walkpkt') | |
47 | def MbufWalkPacket(cmd_args=None): | |
48 | """ Walk the mbuf packet chain (m_nextpkt) | |
49 | """ | |
50 | if not cmd_args: | |
51 | raise ArgumentError("Missing argument 0 in user function.") | |
52 | ||
53 | mp = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') | |
54 | cnt = 1 | |
55 | tot = 0 | |
56 | while (mp): | |
57 | out_string = "" | |
58 | mbuf_walk_packet_format = "{0:4d} 0x{1:x} [len {2:4d}, type {3:2d}, " | |
59 | out_string += mbuf_walk_packet_format.format(cnt, mp, mp.m_hdr.mh_len, mp.m_hdr.mh_type) | |
60 | if (kern.globals.mclaudit != 0): | |
61 | out_string += GetMbufBuf2Mca(mp) + ", " | |
62 | tot = tot + mp.m_hdr.mh_len | |
63 | out_string += "total " + str(tot) + "]" | |
64 | print out_string | |
65 | mp = mp.m_hdr.mh_nextpkt | |
66 | cnt += 1 | |
67 | # EndMacro: mbuf_walkpkt | |
68 | ||
69 | # Macro: mbuf_walk | |
70 | @lldb_command('mbuf_walk') | |
71 | def MbufWalk(cmd_args=None): | |
72 | """ Walk the mbuf chain (m_next) | |
73 | """ | |
74 | mp = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') | |
75 | cnt = 1 | |
76 | tot = 0 | |
77 | while (mp): | |
78 | out_string = "" | |
79 | mbuf_walk_format = "{0:4d} 0x{1:x} [len {2:4d}, type {3:2d}, " | |
80 | out_string += mbuf_walk_format.format(cnt, mp, mp.m_hdr.mh_len, mp.m_hdr.mh_type) | |
81 | if (kern.globals.mclaudit != 0): | |
82 | out_string += GetMbufBuf2Mca(mp) + ", " | |
83 | tot = tot + mp.m_hdr.mh_len | |
84 | out_string += "total " + str(tot) + "]" | |
85 | print out_string | |
86 | mp = mp.m_hdr.mh_next | |
87 | cnt += 1 | |
88 | # EndMacro: mbuf_walk | |
89 | ||
90 | # Macro: mbuf_buf2slab | |
91 | @lldb_command('mbuf_buf2slab') | |
92 | def MbufBuf2Slab(cmd_args=None): | |
93 | """ Given an mbuf object, find its corresponding slab address | |
94 | """ | |
95 | if not cmd_args: | |
96 | raise ArgumentError("Missing argument 0 in user function.") | |
97 | ||
98 | m = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') | |
99 | slab = GetMbufSlab(m) | |
100 | if (kern.ptrsize == 8): | |
101 | mbuf_slab_format = "0x{0:<16x}" | |
102 | print mbuf_slab_format.format(slab) | |
103 | else: | |
104 | mbuf_slab_format = "0x{0:<8x}" | |
105 | print mbuf_slab_format.format(slab) | |
106 | # EndMacro: mbuf_buf2slab | |
107 | ||
108 | # Macro: mbuf_buf2mca | |
109 | @lldb_command('mbuf_buf2mca') | |
110 | def MbufBuf2Mca(cmd_args=None): | |
111 | """ Find the mcache audit structure of the corresponding mbuf | |
112 | """ | |
113 | m = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') | |
114 | print GetMbufBuf2Mca(m) | |
115 | return | |
116 | # EndMacro: mbuf_buf2mca | |
117 | ||
118 | # Macro: mbuf_slabs | |
119 | @lldb_command('mbuf_slabs') | |
120 | def MbufSlabs(cmd_args=None): | |
121 | """ Print all slabs in the group | |
122 | """ | |
123 | ||
124 | out_string = "" | |
125 | if not cmd_args: | |
126 | raise ArgumentError("Invalid arguments passed.") | |
127 | ||
128 | slg = kern.GetValueFromAddress(cmd_args[0], 'mcl_slabg_t *') | |
129 | x = 0 | |
130 | ||
131 | if (kern.ptrsize == 8): | |
132 | slabs_string_format = "{0:>4d}: 0x{1:16x} 0x{2:16x} 0x{3:16x} {4:4s} {5:20d} {6:3d} {7:3d} {8:3d} {9:3d} {10:>6s} " | |
133 | out_string += "slot slab next obj mca tstamp C R N size flags\n" | |
134 | out_string += "---- ------------------ ------------------ ------------------ ------------------ ---------- -- -- -- ------ -----\n" | |
135 | else: | |
136 | slabs_string_format = "{0:>4d}: 0x{1:8x} 0x{2:8x} 0x{3:8x} {4:4s} {5:20d} {6:3d} {7:3d} {8:3d} {9:3d} {10:>6s} " | |
137 | out_string += "slot slab next obj mca tstamp C R N size flags\n" | |
138 | out_string += "---- ---------- ---------- ---------- ---------- ---------- -- -- -- ------ -----\n" | |
139 | ||
140 | mbutl = cast(kern.globals.mbutl, 'unsigned char *') | |
141 | nslabspmb = int((1 << MBSHIFT) >> unsigned(kern.globals.page_shift)) | |
142 | while x < nslabspmb: | |
143 | sl = addressof(slg.slg_slab[x]) | |
144 | mca = 0 | |
145 | obj = sl.sl_base | |
146 | ts = 0 | |
147 | ||
148 | if (kern.globals.mclaudit != 0): | |
149 | mca = GetMbufMcaPtr(obj, sl.sl_class) | |
150 | trn = (mca.mca_next_trn + unsigned(kern.globals.mca_trn_max) - 1) % unsigned(kern.globals.mca_trn_max) | |
151 | ts = mca.mca_trns[trn].mca_tstamp | |
152 | ||
153 | out_string += slabs_string_format.format((x + 1), sl, sl.sl_next, obj, hex(mca), int(ts), int(sl.sl_class), int(sl.sl_refcnt), int(sl.sl_chunks), int(sl.sl_len), hex(sl.sl_flags)) | |
154 | ||
155 | if (sl.sl_flags != 0): | |
156 | out_string += "<" | |
157 | if sl.sl_flags & SLF_MAPPED: | |
158 | out_string += "mapped" | |
159 | if sl.sl_flags & SLF_PARTIAL: | |
160 | out_string += ",partial" | |
161 | if sl.sl_flags & SLF_DETACHED: | |
162 | out_string += ",detached" | |
163 | out_string += ">" | |
164 | out_string += "\n" | |
165 | ||
166 | if sl.sl_chunks > 1: | |
167 | z = 1 | |
168 | c = sl.sl_len/sl.sl_chunks | |
169 | ||
170 | while z < sl.sl_chunks: | |
171 | obj = sl.sl_base + (c * z) | |
172 | mca = 0 | |
173 | ts = 0 | |
174 | ||
175 | if (kern.globals.mclaudit != 0): | |
176 | mca = GetMbufMcaPtr(obj, sl.sl_class) | |
177 | trn = (mca.mca_next_trn + unsigned(kern.globals.mca_trn_max) - 1) % unsigned(kern.globals.mca_trn_max) | |
178 | ts = mca.mca_trns[trn].mca_tstamp | |
179 | ||
180 | if (kern.ptrsize == 8): | |
181 | out_string += " " + hex(obj) + " " + hex(mca) + " " + str(unsigned(ts)) + "\n" | |
182 | else: | |
183 | out_string += " " + hex(obj) + " " + hex(mca) + " " + str(unsigned(ts)) + "\n" | |
184 | ||
185 | z += 1 | |
186 | x += 1 | |
187 | print out_string | |
188 | # EndMacro: mbuf_slabs | |
189 | ||
190 | # Macro: mbuf_slabstbl | |
191 | @lldb_command('mbuf_slabstbl') | |
192 | def MbufSlabsTbl(cmd_args=None): | |
193 | """ Print slabs table | |
194 | """ | |
195 | out_string = "" | |
196 | x = 0 | |
197 | ||
198 | if (kern.ptrsize == 8): | |
199 | out_string += "slot slabg slabs range\n" | |
200 | out_string += "---- ------------------ -------------------------------------------\n" | |
201 | else: | |
202 | out_string += "slot slabg slabs range\n" | |
203 | out_string += "---- ---------- ---------------------------\n" | |
204 | ||
205 | slabstbl = kern.globals.slabstbl | |
206 | slabs_table_blank_string_format = "{0:>3d}: - \n" | |
207 | nslabspmb = int(((1 << MBSHIFT) >> unsigned(kern.globals.page_shift))) | |
208 | while (x < unsigned(kern.globals.maxslabgrp)): | |
209 | slg = slabstbl[x] | |
210 | if (slg == 0): | |
211 | out_string += slabs_table_blank_string_format.format(x+1) | |
212 | else: | |
213 | if (kern.ptrsize == 8): | |
214 | slabs_table_string_format = "{0:>3d}: 0x{1:16x} [ 0x{2:16x} - 0x{3:16x} ]\n" | |
215 | out_string += slabs_table_string_format.format(x+1, slg, addressof(slg.slg_slab[0]), addressof(slg.slg_slab[nslabspmb-1])) | |
216 | else: | |
217 | slabs_table_string_format = "{0:>3d}: 0x{1:8x} [ 0x{2:8x} - 0x{3:8x} ]\n" | |
218 | out_string += slabs_table_string_format.format(x+1, slg, addressof(slg.slg_slab[0]), addressof(slg.slg_slab[nslabspmb-1])) | |
219 | ||
220 | x += 1 | |
221 | print out_string | |
222 | # EndMacro: mbuf_slabstbl | |
223 | ||
224 | def GetMbufMcaPtr(m, cl): | |
225 | pgshift = int(kern.globals.page_shift) | |
226 | ix = int((m - Cast(kern.globals.mbutl, 'char *')) >> pgshift) | |
227 | page_addr = (Cast(kern.globals.mbutl, 'char *') + (ix << pgshift)) | |
228 | ||
229 | if (int(cl) == 0): | |
230 | midx = int((m - page_addr) >> 8) | |
231 | mca = kern.globals.mclaudit[ix].cl_audit[midx] | |
232 | elif (int(cl) == 1): | |
233 | midx = int((m - page_addr) >> 11) | |
234 | mca = kern.globals.mclaudit[ix].cl_audit[midx] | |
235 | elif (int(cl) == 2): | |
236 | midx = int((m - page_addr) >> 12) | |
237 | mca = kern.globals.mclaudit[ix].cl_audit[midx] | |
238 | else: | |
239 | mca = kern.globals.mclaudit[ix].cl_audit[0] | |
240 | return Cast(mca, 'mcache_audit_t *') | |
241 | ||
242 | def GetMbufSlab(m): | |
243 | pgshift = int(kern.globals.page_shift) | |
244 | gix = int((Cast(m, 'char *') - Cast(kern.globals.mbutl, 'char *')) >> MBSHIFT) | |
245 | slabstbl = kern.globals.slabstbl | |
246 | ix = int((Cast(m, 'char *') - Cast(slabstbl[gix].slg_slab[0].sl_base, 'char *')) >> pgshift) | |
247 | return addressof(slabstbl[gix].slg_slab[ix]) | |
248 | ||
249 | def GetMbufBuf2Mca(m): | |
250 | sl = GetMbufSlab(m) | |
251 | mca = GetMbufMcaPtr(m, sl.sl_class) | |
252 | return str(mca) | |
253 | ||
254 | def GetMbufWalkAllSlabs(show_a, show_f, show_tr): | |
255 | out_string = "" | |
256 | ||
257 | kern.globals.slabstbl[0] | |
258 | ||
259 | x = 0 | |
260 | total = 0 | |
261 | total_a = 0 | |
262 | total_f = 0 | |
263 | ||
264 | if (show_a and not(show_f)): | |
265 | out_string += "Searching only for active... \n" | |
266 | if (not(show_a) and show_f): | |
267 | out_string += "Searching only for inactive... \n" | |
268 | if (show_a and show_f): | |
269 | out_string += "Displaying all... \n" | |
270 | ||
271 | if (kern.ptrsize == 8): | |
272 | show_mca_string_format = "{0:>4s} {1:>4s} {2:>16s} {3:>16s} {4:>16} {5:>12s} {6:12s}" | |
273 | out_string += show_mca_string_format.format("slot", "idx", "slab address", "mca address", "obj address", "type", "allocation state\n") | |
274 | else: | |
275 | show_mca_string_format = "{0:4s} {1:4s} {2:8s} {3:8s} {4:8} {5:12s} {6:12s}" | |
276 | out_string += show_mca_string_format.format("slot", "idx", "slab address", "mca address", "obj address", "type", "allocation state\n") | |
277 | ||
278 | nslabspmb = unsigned((1 << MBSHIFT) >> unsigned(kern.globals.page_shift)) | |
279 | while (x < unsigned(kern.globals.slabgrp)): | |
280 | slg = kern.globals.slabstbl[x] | |
281 | y = 0 | |
282 | stop = 0 | |
283 | while ((y < nslabspmb) and (stop == 0)): | |
284 | sl = addressof(slg.slg_slab[y]) | |
285 | base = sl.sl_base | |
286 | mca = GetMbufMcaPtr(base, sl.sl_class) | |
287 | first = 1 | |
288 | ||
289 | while ((Cast(mca, 'int') != 0) and (unsigned(mca.mca_addr) != 0)): | |
290 | printmca = 0 | |
291 | if (mca.mca_uflags & (MB_INUSE | MB_COMP_INUSE)): | |
292 | total_a = total_a + 1 | |
293 | printmca = show_a | |
294 | else: | |
295 | total_f = total_f + 1 | |
296 | printmca = show_f | |
297 | ||
298 | if (printmca != 0): | |
299 | if (first == 1): | |
300 | if (kern.ptrsize == 8): | |
301 | mca_string_format = "{0:4d} {1:4d} 0x{2:16x} " | |
302 | out_string += mca_string_format.format(x, y, sl) | |
303 | else: | |
304 | mca_string_format = "{0:4d} {1:4d} 0x{02:8x} " | |
305 | out_string += mca_string_format.format(x, y, sl) | |
306 | else: | |
307 | if (kern.ptrsize == 8): | |
308 | out_string += " " | |
309 | else: | |
310 | out_string += " " | |
311 | ||
312 | if (kern.ptrsize == 8): | |
313 | mca_string_format = "0x{0:16x} 0x{1:16x}" | |
314 | out_string += mca_string_format.format(mca, mca.mca_addr) | |
315 | else: | |
316 | mca_string_format = "0x{0:8x} 0x{1:8x}" | |
317 | out_string += mca_string_format.format(mca, mca.mca_addr) | |
318 | ||
319 | out_string += GetMbufMcaCtype(mca, 0) | |
320 | ||
321 | if (mca.mca_uflags & (MB_INUSE | MB_COMP_INUSE)): | |
322 | out_string += "active " | |
323 | else: | |
324 | out_string += " freed " | |
325 | if (first == 1): | |
326 | first = 0 | |
327 | out_string += "\n" | |
328 | total = total + 1 | |
329 | ||
330 | if (show_tr != 0): | |
331 | if (mca.mca_next_trn == 0): | |
332 | trn = 1 | |
333 | else: | |
334 | trn = 0 | |
335 | out_string += "Transaction " + str(int(trn)) + " at " + str(int(mca.mca_trns[int(trn)].mca_tstamp)) + " by thread: 0x" + str(hex(mca.mca_trns[int(trn)].mca_thread)) + ":\n" | |
336 | cnt = 0 | |
337 | while (cnt < mca.mca_trns[int(trn)].mca_depth): | |
338 | kgm_pc = mca.mca_trns[int(trn)].mca_stack[int(cnt)] | |
339 | out_string += str(int(cnt) + 1) + " " | |
340 | out_string += GetPc(kgm_pc) | |
341 | cnt += 1 | |
342 | ||
343 | print out_string | |
344 | out_string = "" | |
345 | mca = mca.mca_next | |
346 | ||
347 | y += 1 | |
348 | if (slg.slg_slab[int(y)].sl_base == 0): | |
349 | stop = 1 | |
350 | x += 1 | |
351 | ||
352 | if (total and show_a and show_f): | |
353 | out_string += "total objects = " + str(int(total)) + "\n" | |
354 | out_string += "active/unfreed objects = " + str(int(total_a)) + "\n" | |
355 | out_string += "freed/in_cache objects = " + str(int(total_f)) + "\n" | |
356 | ||
357 | return out_string | |
358 | ||
359 | def GetMbufMcaCtype(mca, vopt): | |
360 | cp = mca.mca_cache | |
361 | mca_class = unsigned(cp.mc_private) | |
362 | csize = unsigned(kern.globals.mbuf_table[mca_class].mtbl_stats.mbcl_size) | |
363 | done = 0 | |
364 | out_string = " " | |
365 | if (csize == MSIZE): | |
366 | if (vopt): | |
367 | out_string += "M (mbuf) " | |
368 | else: | |
369 | out_string += "M " | |
370 | return out_string | |
371 | if (csize == MCLBYTES): | |
372 | if (vopt): | |
373 | out_string += "CL (2K cluster) " | |
374 | else: | |
375 | out_string += "CL " | |
376 | return out_string | |
377 | if (csize == MBIGCLBYTES): | |
378 | if (vopt): | |
379 | out_string += "BCL (4K cluster) " | |
380 | else: | |
381 | out_string += "BCL " | |
382 | return out_string | |
383 | if (csize == M16KCLBYTES): | |
384 | if (vopt): | |
385 | out_string += "JCL (16K cluster) " | |
386 | else: | |
387 | out_string += "JCL " | |
388 | return out_string | |
389 | ||
390 | if (csize == (MSIZE + MCLBYTES)): | |
391 | if (mca.mca_uflags & MB_SCVALID): | |
392 | if (mca.mca_uptr): | |
393 | out_string += "M+CL " | |
394 | if vopt: | |
395 | out_string += "(paired mbuf, 2K cluster) " | |
396 | else: | |
397 | out_string += "M-CL " | |
398 | if vopt: | |
399 | out_string += "(unpaired mbuf, 2K cluster) " | |
400 | else: | |
401 | if (mca.mca_uptr): | |
402 | out_string += "CL+M " | |
403 | if vopt: | |
404 | out_string += "(paired 2K cluster, mbuf) " | |
405 | else: | |
406 | out_string += "CL-M " | |
407 | if vopt: | |
408 | out_string += "(unpaired 2K cluster, mbuf) " | |
409 | return out_string | |
410 | ||
411 | if (csize == (MSIZE + MBIGCLBYTES)): | |
412 | if (mca.mca_uflags & MB_SCVALID): | |
413 | if (mca.mca_uptr): | |
414 | out_string += "M+BCL " | |
415 | if vopt: | |
416 | out_string += "(paired mbuf, 4K cluster) " | |
417 | else: | |
418 | out_string += "M-BCL " | |
419 | if vopt: | |
420 | out_string += "(unpaired mbuf, 4K cluster) " | |
421 | else: | |
422 | if (mca.mca_uptr): | |
423 | out_string += "BCL+M " | |
424 | if vopt: | |
425 | out_string += "(paired 4K cluster, mbuf) " | |
426 | else: | |
427 | out_string += "BCL-m " | |
428 | if vopt: | |
429 | out_string += "(unpaired 4K cluster, mbuf) " | |
430 | return out_string | |
431 | ||
432 | if (csize == (MSIZE + M16KCLBYTES)): | |
433 | if (mca.mca_uflags & MB_SCVALID): | |
434 | if (mca.mca_uptr): | |
435 | out_string += "M+BCL " | |
436 | if vopt: | |
437 | out_string += "(paired mbuf, 4K cluster) " | |
438 | else: | |
439 | out_string += "M-BCL " | |
440 | if vopt: | |
441 | out_string += "(unpaired mbuf, 4K cluster) " | |
442 | else: | |
443 | if (mca.mca_uptr): | |
444 | out_string += "BCL+M " | |
445 | if vopt: | |
446 | out_string += "(paired 4K cluster, mbuf) " | |
447 | else: | |
448 | out_string += "BCL-m " | |
449 | if vopt: | |
450 | out_string += "(unpaired 4K cluster, mbuf) " | |
451 | return out_string | |
452 | ||
453 | out_string += "unknown: " + cp.mc_name | |
454 | return out_string | |
455 | ||
456 | kgm_pkmod = 0 | |
457 | kgm_pkmodst = 0 | |
458 | kgm_pkmoden = 0 | |
459 | ||
460 | def GetPointerAsString(kgm_pc): | |
461 | if (kern.ptrsize == 8): | |
462 | pointer_format_string = "0x{0:<16x} " | |
463 | else: | |
464 | pointer_format_string = "0x{0:<8x} " | |
465 | return pointer_format_string.format(kgm_pc) | |
466 | ||
467 | def GetPc(kgm_pc): | |
468 | out_string = GetSourceInformationForAddress(unsigned(kgm_pc)) + "\n" | |
469 | return out_string | |
470 | ||
471 | ||
472 | # Macro: mbuf_showactive | |
473 | @lldb_command('mbuf_showactive') | |
474 | def MbufShowActive(cmd_args=None): | |
475 | """ Print all active/in-use mbuf objects | |
476 | """ | |
477 | if cmd_args: | |
478 | print GetMbufWalkAllSlabs(1, 0, cmd_args[0]) | |
479 | else: | |
480 | print GetMbufWalkAllSlabs(1, 0, 0) | |
481 | # EndMacro: mbuf_showactive | |
482 | ||
483 | ||
484 | # Macro: mbuf_showinactive | |
485 | @lldb_command('mbuf_showinactive') | |
486 | def MbufShowInactive(cmd_args=None): | |
487 | """ Print all freed/in-cache mbuf objects | |
488 | """ | |
489 | print GetMbufWalkAllSlabs(0, 1, 0) | |
490 | # EndMacro: mbuf_showinactive | |
491 | ||
492 | ||
493 | # Macro: mbuf_showmca | |
494 | @lldb_command('mbuf_showmca') | |
495 | def MbufShowMca(cmd_args=None): | |
496 | """ Print the contents of an mbuf mcache audit structure | |
497 | """ | |
498 | out_string = "" | |
499 | pgshift = unsigned(kern.globals.page_shift) | |
500 | if cmd_args: | |
501 | mca = kern.GetValueFromAddress(cmd_args[0], 'mcache_audit_t *') | |
502 | cp = mca.mca_cache | |
503 | out_string += "object type:\t" | |
504 | out_string += GetMbufMcaCtype(mca, 1) | |
505 | out_string += "\nControlling mcache :\t" + hex(mca.mca_cache) + " (" + str(cp.mc_name) + ")\n" | |
506 | if (mca.mca_uflags & MB_SCVALID): | |
507 | mbutl = Cast(kern.globals.mbutl, 'unsigned char *') | |
508 | ix = (mca.mca_addr - mbutl) >> pgshift | |
509 | clbase = mbutl + (ix << pgshift) | |
510 | mclidx = (mca.mca_addr - clbase) >> 8 | |
511 | out_string += "mbuf obj :\t\t" + hex(mca.mca_addr) + "\n" | |
512 | out_string += "mbuf index :\t\t" + str(mclidx + 1) + " (out of 16) in cluster base " + hex(clbase) + "\n" | |
513 | if (int(mca.mca_uptr) != 0): | |
514 | peer_mca = cast(mca.mca_uptr, 'mcache_audit_t *') | |
515 | out_string += "paired cluster obj :\t" + hex(peer_mca.mca_addr) + " (mca " + hex(peer_mca) + ")\n" | |
516 | out_string += "saved contents :\t" + hex(mca.mca_contents) + " (" + str(int(mca.mca_contents_size)) + " bytes)\n" | |
517 | else: | |
518 | out_string += "cluster obj :\t\t" + hex(mca.mca_addr) + "\n" | |
519 | if (mca.mca_uptr != 0): | |
520 | peer_mca = cast(mca.mca_uptr, 'mcache_audit_t *') | |
521 | out_string += "paired mbuf obj :\t" + hex(peer_mca.mca_addr) + " (mca " + hex(peer_mca) + ")\n" | |
522 | ||
523 | for idx in range(unsigned(kern.globals.mca_trn_max), 0, -1): | |
524 | trn = (mca.mca_next_trn + idx - 1) % unsigned(kern.globals.mca_trn_max) | |
525 | out_string += "transaction {:d} (tstamp {:d}, thread 0x{:x}):\n".format(trn, mca.mca_trns[trn].mca_tstamp, mca.mca_trns[trn].mca_thread) | |
526 | cnt = 0 | |
527 | while (cnt < mca.mca_trns[trn].mca_depth): | |
528 | kgm_pc = mca.mca_trns[trn].mca_stack[cnt] | |
529 | out_string += " " + str(cnt + 1) + ". " | |
530 | out_string += GetPc(kgm_pc) | |
531 | cnt += 1 | |
532 | ||
533 | msc = cast(mca.mca_contents, 'mcl_saved_contents_t *') | |
534 | msa = addressof(msc.sc_scratch) | |
535 | if (mca.mca_uflags & MB_SCVALID): | |
536 | if (msa.msa_depth > 0): | |
537 | out_string += "Recent scratch transaction (tstamp {:d}, thread 0x{:x}):\n".format(msa.msa_tstamp, msa.msa_thread) | |
538 | cnt = 0 | |
539 | while (cnt < msa.msa_depth): | |
540 | kgm_pc = msa.msa_stack[cnt] | |
541 | out_string += " " + str(cnt + 1) + ". " | |
542 | out_string += GetPc(kgm_pc) | |
543 | cnt += 1 | |
544 | ||
545 | if (msa.msa_pdepth > 0): | |
546 | out_string += "previous scratch transaction (tstamp {:d}, thread 0x{:x}):\n".format(msa.msa_ptstamp, msa.msa_pthread) | |
547 | if (msa): | |
548 | cnt = 0 | |
549 | while (cnt < msa.msa_pdepth): | |
550 | kgm_pc = msa.msa_pstack[cnt] | |
551 | out_string += " " + str(cnt + 1) + ". " | |
552 | out_string += GetPc(kgm_pc) | |
553 | cnt += 1 | |
554 | else: | |
555 | out_string += "Missing argument 0 in user function." | |
556 | ||
557 | print out_string | |
558 | # EndMacro: mbuf_showmca | |
559 | ||
560 | ||
561 | # Macro: mbuf_showall | |
562 | @lldb_command('mbuf_showall') | |
563 | def MbufShowAll(cmd_args=None): | |
564 | """ Print all mbuf objects | |
565 | """ | |
566 | print GetMbufWalkAllSlabs(1, 1, 0) | |
567 | # EndMacro: mbuf_showall | |
568 | ||
569 | # Macro: mbuf_countchain | |
570 | @lldb_command('mbuf_countchain') | |
571 | def MbufCountChain(cmd_args=None): | |
572 | """ Count the length of an mbuf chain | |
573 | """ | |
574 | if not cmd_args: | |
575 | raise ArgumentError("Missing argument 0 in user function.") | |
576 | ||
577 | mp = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') | |
578 | ||
579 | pkt = 0 | |
580 | nxt = 0 | |
581 | ||
582 | while (mp): | |
583 | pkt = pkt + 1 | |
584 | mn = mp.m_hdr.mh_next | |
585 | while (mn): | |
586 | nxt = nxt + 1 | |
587 | mn = mn.m_hdr.mh_next | |
588 | ||
589 | mp = mp.m_hdr.mh_nextpkt | |
590 | ||
591 | if (((pkt + nxt) % 50) == 0): | |
592 | print " ..." + str(pkt_nxt) | |
593 | ||
594 | print "Total: " + str(pkt + nxt) + " (via m_next: " + str(nxt) + ")" | |
595 | # EndMacro: mbuf_countchain | |
596 | ||
597 | ||
598 | ||
599 | # Macro: mbuf_topleak | |
600 | @lldb_command('mbuf_topleak') | |
601 | def MbufTopLeak(cmd_args=None): | |
602 | """ Print the top suspected mbuf leakers | |
603 | """ | |
604 | topcnt = 0 | |
605 | if (int(len(cmd_args)) > 0 and int(cmd_args[0]) < 5): | |
606 | maxcnt = cmd_args[0] | |
607 | else: | |
608 | maxcnt = 5 | |
609 | while (topcnt < maxcnt): | |
610 | print GetMbufTraceLeak(kern.globals.mleak_top_trace[topcnt]) | |
611 | topcnt += 1 | |
612 | ||
613 | # EndMacro: mbuf_topleak | |
614 | ||
615 | def GetMbufTraceLeak(trace): | |
616 | out_string = "" | |
617 | if (trace.allocs != 0): | |
618 | out_string += hex(trace) + ":" + str(trace.allocs) + " outstanding allocs\n" | |
619 | out_string += "Backtrace saved " + str(trace.depth) + " deep\n" | |
620 | if (trace.depth != 0): | |
621 | cnt = 0 | |
622 | while (cnt < trace.depth): | |
623 | out_string += str(cnt + 1) + ": " | |
624 | out_string += GetPc(trace.addr[cnt]) | |
625 | out_string += "\n" | |
626 | cnt += 1 | |
627 | return out_string | |
628 | ||
629 | ||
630 | # Macro: mbuf_traceleak | |
631 | @lldb_command('mbuf_traceleak') | |
632 | def MbufTraceLeak(cmd_args=None): | |
633 | """ Print the leak information for a given leak address | |
634 | Given an mbuf leak trace (mtrace) structure address, print out the | |
635 | stored information with that trace | |
636 | syntax: (lldb) mbuf_traceleak <addr> | |
637 | """ | |
638 | if not cmd_args: | |
639 | raise ArgumentError("Missing argument 0 in user function.") | |
640 | ||
641 | trace = kern.GetValueFromAddress(cmd_args[0], 'mtrace *') | |
642 | print GetMbufTraceLeak(trace) | |
643 | # EndMacro: mbuf_traceleak | |
644 | ||
645 | ||
646 | # Macro: mcache_walkobj | |
647 | @lldb_command('mcache_walkobj') | |
648 | def McacheWalkObject(cmd_args=None): | |
649 | """ Given a mcache object address, walk its obj_next pointer | |
650 | """ | |
651 | if not cmd_args: | |
652 | raise ArgumentError("Missing argument 0 in user function.") | |
653 | ||
654 | out_string = "" | |
655 | p = kern.GetValueFromAddress(cmd_args[0], 'mcache_obj_t *') | |
656 | cnt = 1 | |
657 | total = 0 | |
658 | while (p): | |
659 | mcache_object_format = "{0:>4d}: 0x{1:>16x}" | |
660 | out_string += mcache_object_format.format(cnt, p) + "\n" | |
661 | p = p.obj_next | |
662 | cnt += 1 | |
663 | print out_string | |
664 | # EndMacro: mcache_walkobj | |
665 | ||
666 | # Macro: mcache_stat | |
667 | @lldb_command('mcache_stat') | |
668 | def McacheStat(cmd_args=None): | |
669 | """ Print all mcaches in the system. | |
670 | """ | |
671 | head = kern.globals.mcache_head | |
672 | out_string = "" | |
673 | mc = cast(head.lh_first, 'mcache *') | |
674 | if (kern.ptrsize == 8): | |
675 | mcache_stat_format_string = "{0:<24s} {1:>8s} {2:>20s} {3:>5s} {4:>5s} {5:>20s} {6:>30s} {7:>18s}" | |
676 | else: | |
677 | mcache_stat_format_string = "{0:<24s} {1:>8s} {2:>12s} {3:>5s} {4:>5s} {5:>12s} {6:>30s} {7:>18s}" | |
678 | ||
679 | if (kern.ptrsize == 8): | |
680 | mcache_stat_data_format_string = "{0:<24s} {1:>12s} {2:>20s} {3:>5s} {4:>5s} {5:>22s} {6:>12d} {7:>8d} {8:>8d} {9:>18d}" | |
681 | else: | |
682 | mcache_stat_data_format_string = "{0:<24s} {1:>12s} {2:>12s} {3:>5s} {4:>5s} {5:>14s} {6:>12d} {7:>8d} {8:>8d} {9:>18d}" | |
683 | ||
684 | out_string += mcache_stat_format_string.format("cache name", "cache state", "cache addr", "buf size", "buf align", "backing zone", "wait nowait failed", "bufs incache") | |
685 | out_string += "\n" | |
686 | ||
687 | ncpu = int(kern.globals.ncpu) | |
688 | while mc != 0: | |
689 | bktsize = mc.mc_cpu[0].cc_bktsize | |
690 | cache_state = "" | |
691 | if (mc.mc_flags & MCF_NOCPUCACHE): | |
692 | cache_state = "disabled" | |
693 | else: | |
694 | if (bktsize == 0): | |
695 | cache_state = " offline" | |
696 | else: | |
697 | cache_state = " online" | |
698 | if (mc.mc_slab_zone != 0): | |
699 | backing_zone = mc.mc_slab_zone | |
700 | else: | |
701 | if (kern.ptrsize == 8): | |
702 | backing_zone = " custom" | |
703 | else: | |
704 | backing_zone = " custom" | |
705 | ||
706 | total = 0 | |
707 | total += mc.mc_full.bl_total * bktsize | |
708 | n = 0 | |
709 | while(n < ncpu): | |
710 | ccp = mc.mc_cpu[n] | |
711 | if (ccp.cc_objs > 0): | |
712 | total += ccp.cc_objs | |
713 | if (ccp.cc_pobjs > 0): | |
714 | total += ccp.cc_pobjs | |
715 | n += 1 | |
716 | ccp += 1 | |
717 | ||
718 | out_string += mcache_stat_data_format_string.format(mc.mc_name, cache_state, hex(mc), str(int(mc.mc_bufsize)), str(int(mc.mc_align)), hex(mc.mc_slab_zone), int(mc.mc_wretry_cnt), int(mc.mc_nwretry_cnt), int(mc.mc_nwfail_cnt), total) | |
719 | out_string += "\n" | |
720 | mc = cast(mc.mc_list.le_next, 'mcache *') | |
721 | print out_string | |
722 | # EndMacro: mcache_stat | |
723 | ||
724 | # Macro: mcache_showcache | |
725 | @lldb_command('mcache_showcache') | |
726 | def McacheShowCache(cmd_args=None): | |
727 | """Display the number of objects in cache. | |
728 | """ | |
729 | out_string = "" | |
730 | cp = kern.GetValueFromAddress(cmd_args[0], 'mcache_t *') | |
731 | bktsize = cp.mc_cpu[0].cc_bktsize | |
732 | cnt = 0 | |
733 | total = 0 | |
734 | mcache_cache_format = "{0:<4d} {1:>8d} {2:>8d} {3:>8d}" | |
735 | out_string += "Showing cache " + str(cp.mc_name) + " :\n\n" | |
736 | out_string += " CPU cc_objs cc_pobjs total\n" | |
737 | out_string += "---- ------- -------- --------\n" | |
738 | ncpu = int(kern.globals.ncpu) | |
739 | while (cnt < ncpu): | |
740 | ccp = cp.mc_cpu[cnt] | |
741 | objs = ccp.cc_objs | |
742 | if (objs <= 0): | |
743 | objs = 0 | |
744 | pobjs = ccp.cc_pobjs | |
745 | if (pobjs <= 0): | |
746 | pobjs = 0 | |
747 | tot_cpu = objs + pobjs | |
748 | total += tot_cpu | |
749 | out_string += mcache_cache_format.format(cnt, objs, pobjs, tot_cpu) | |
750 | out_string += "\n" | |
751 | cnt += 1 | |
752 | ||
753 | out_string += " ========\n" | |
754 | out_string += " " + str(total) + "\n\n" | |
755 | total += cp.mc_full.bl_total * bktsize | |
756 | ||
757 | out_string += "Total # of full buckets (" + str(int(bktsize)) + " objs/bkt):\t" + str(int(cp.mc_full.bl_total)) + "\n" | |
758 | out_string += "Total # of objects cached:\t\t" + str(total) + "\n" | |
759 | print out_string | |
760 | # EndMacro: mcache_showcache |