]>
Commit | Line | Data |
---|---|---|
39236c6e A |
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 (cmd_args == None or len(cmd_args) == 0): | |
51 | print "Missing argument 0 in user function." | |
52 | return | |
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 (cmd_args == None or len(cmd_args) == 0): | |
96 | print "Missing argument 0 in user function." | |
97 | return | |
98 | m = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') | |
99 | gix = (m - Cast(kern.globals.mbutl, 'char *')) >> MBSHIFT | |
100 | slabstbl = kern.globals.slabstbl | |
101 | ix = (m - Cast(slabstbl[int(gix)].slg_slab[0].sl_base, 'char *')) >> 12 | |
102 | slab = addressof(slabstbl[int(gix)].slg_slab[int(ix)]) | |
103 | if (kern.ptrsize == 8): | |
104 | mbuf_slab_format = "0x{0:<16x}" | |
105 | print mbuf_slab_format.format(slab) | |
106 | else: | |
107 | mbuf_slab_format = "0x{0:<8x}" | |
108 | print mbuf_slab_format.format(slab) | |
109 | # EndMacro: mbuf_buf2slab | |
110 | ||
111 | # Macro: mbuf_buf2mca | |
112 | @lldb_command('mbuf_buf2mca') | |
113 | def MbufBuf2Mca(cmd_args=None): | |
114 | """ Find the mcache audit structure of the corresponding mbuf | |
115 | """ | |
116 | m = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') | |
117 | print GetMbufBuf2Mca(m) | |
118 | return | |
119 | # EndMacro: mbuf_buf2mca | |
120 | ||
121 | # Macro: mbuf_slabs | |
122 | @lldb_command('mbuf_slabs') | |
123 | def MbufSlabs(cmd_args=None): | |
124 | """ Print all slabs in the group | |
125 | """ | |
126 | out_string = "" | |
127 | slg = kern.GetValueFromAddress(cmd_args[0], 'mcl_slabg_t *') | |
128 | x = 0 | |
129 | ||
130 | if (kern.ptrsize == 8): | |
131 | 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} " | |
132 | out_string += "slot slab next obj mca tstamp C R N size flags\n" | |
133 | out_string += "---- ------------------ ------------------ ------------------ ------------------ ---------- -- -- -- ------ -----\n" | |
134 | else: | |
135 | 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} " | |
136 | out_string += "slot slab next obj mca tstamp C R N size flags\n" | |
137 | out_string += "---- ---------- ---------- ---------- ---------- ---------- -- -- -- ------ -----\n" | |
138 | ||
139 | mbutl = cast(kern.globals.mbutl, 'union mbigcluster *') | |
140 | while x < NSLABSPMB: | |
141 | sl = addressof(slg.slg_slab[x]) | |
142 | mca = 0 | |
143 | obj = sl.sl_base | |
144 | ts = 0 | |
145 | ||
146 | if (kern.globals.mclaudit != 0): | |
147 | ix = (obj - Cast(kern.globals.mbutl, 'char *')) >> 12 | |
148 | clbase = mbutl + (sizeof(dereference(mbutl)) * ix) | |
149 | mclidx = (obj - clbase) >> 8 | |
150 | mca = kern.globals.mclaudit[int(ix)].cl_audit[int(mclidx)] | |
151 | ts = mca.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 | ix = (obj - Cast(kern.globals.mbutl, 'char *')) >> 12 | |
177 | clbase = mbutl + (sizeof(dereference(mbutl)) * ix) | |
178 | mclidx = (obj - clbase) >> 8 | |
179 | mca = kern.globals.mclaudit[int(ix)].cl_audit[int(mclidx)] | |
180 | ts = mca.mca_tstamp | |
181 | ||
182 | if (kern.ptrsize == 8): | |
183 | out_string += " " + hex(obj) + " " + hex(mca) + " " + str(unsigned(ts)) + "\n" | |
184 | else: | |
185 | out_string += " " + hex(obj) + " " + hex(mca) + " " + str(unsigned(ts)) + "\n" | |
186 | ||
187 | z += 1 | |
188 | x += 1 | |
189 | print out_string | |
190 | # EndMacro: mbuf_slabs | |
191 | ||
192 | # Macro: mbuf_slabstbl | |
193 | @lldb_command('mbuf_slabstbl') | |
194 | def MbufSlabsTbl(cmd_args=None): | |
195 | """ Print slabs table | |
196 | """ | |
197 | out_string = "" | |
198 | x = 0 | |
199 | ||
200 | if (kern.ptrsize == 8): | |
201 | out_string += "slot slabg slabs range\n" | |
202 | out_string += "---- ------------------ -------------------------------------------\n" | |
203 | else: | |
204 | out_string += "slot slabg slabs range\n" | |
205 | out_string += "---- ---------- ---------------------------\n" | |
206 | ||
207 | slabstbl = kern.globals.slabstbl | |
208 | slabs_table_blank_string_format = "{0:>3d}: - \n" | |
209 | while (x < unsigned(kern.globals.maxslabgrp)): | |
210 | slg = slabstbl[x] | |
211 | if (slg == 0): | |
212 | out_string += slabs_table_blank_string_format.format(x+1) | |
213 | else: | |
214 | if (kern.ptrsize == 8): | |
215 | slabs_table_string_format = "{0:>3d}: 0x{1:16x} [ 0x{2:16x} - 0x{3:16x} ]\n" | |
216 | out_string += slabs_table_string_format.format(x+1, slg, addressof(slg.slg_slab[0]), addressof(slg.slg_slab[NSLABSPMB-1])) | |
217 | else: | |
218 | slabs_table_string_format = "{0:>3d}: 0x{1:8x} [ 0x{2:8x} - 0x{3:8x} ]\n" | |
219 | out_string += slabs_table_string_format.format(x+1, slg, addressof(slg.slg_slab[0]), addressof(slg.slg_slab[NSLABSPMB-1])) | |
220 | ||
221 | x += 1 | |
222 | print out_string | |
223 | # EndMacro: mbuf_slabstbl | |
224 | ||
225 | ||
226 | def GetMbufBuf2Mca(m): | |
227 | ix = (m - Cast(kern.globals.mbutl, 'char *')) >> 12 | |
228 | #mbutl = Cast(kern.globals.mbutl, 'union mbigcluster *') | |
229 | mbutl = cast(kern.globals.mbutl, 'union mbigcluster *') | |
230 | clbase = mbutl + (sizeof(dereference(mbutl)) * ix) | |
231 | mclidx = (m - clbase) >> 8 | |
232 | mca = kern.globals.mclaudit[int(ix)].cl_audit[int(mclidx)] | |
233 | return str(mca) | |
234 | ||
235 | def GetMbufWalkAllSlabs(show_a, show_f, show_tr): | |
236 | out_string = "" | |
237 | ||
238 | kern.globals.slabstbl[0] | |
239 | ||
240 | x = 0 | |
241 | total = 0 | |
242 | total_a = 0 | |
243 | total_f = 0 | |
244 | ||
245 | if (show_a and not(show_f)): | |
246 | out_string += "Searching only for active... \n" | |
247 | if (not(show_a) and show_f): | |
248 | out_string += "Searching only for inactive... \n" | |
249 | if (show_a and show_f): | |
250 | out_string += "Displaying all... \n" | |
251 | ||
252 | if (kern.ptrsize == 8): | |
253 | show_mca_string_format = "{0:>4s} {1:>4s} {2:>16s} {3:>16s} {4:>16} {5:>12s} {6:12s}" | |
254 | out_string += show_mca_string_format.format("slot", "idx", "slab address", "mca address", "obj address", "type", "allocation state\n") | |
255 | else: | |
256 | show_mca_string_format = "{0:4s} {1:4s} {2:8s} {3:8s} {4:8} {5:12s} {6:12s}" | |
257 | out_string += show_mca_string_format.format("slot", "idx", "slab address", "mca address", "obj address", "type", "allocation state\n") | |
258 | ||
259 | while (x < unsigned(kern.globals.slabgrp)): | |
260 | slg = kern.globals.slabstbl[x] | |
261 | y = 0 | |
262 | stop = 0 | |
263 | while ((y < NSLABSPMB) and (stop == 0)): | |
264 | sl = addressof(slg.slg_slab[y]) | |
265 | base = sl.sl_base | |
266 | mbutl = cast(kern.globals.mbutl, 'union mbigcluster *') | |
267 | ix = (base - mbutl) >> 12 | |
268 | clbase = mbutl + (sizeof(dereference(mbutl)) * ix) | |
269 | mclidx = (base - clbase) >> 8 | |
270 | mca = kern.globals.mclaudit[int(ix)].cl_audit[int(mclidx)] | |
271 | first = 1 | |
272 | ||
273 | while ((Cast(mca, 'int') != 0) and (unsigned(mca.mca_addr) != 0)): | |
274 | printmca = 0 | |
275 | if (mca.mca_uflags & (MB_INUSE|MB_COMP_INUSE)): | |
276 | total_a = total_a + 1 | |
277 | printmca = show_a | |
278 | else: | |
279 | total_f = total_f + 1 | |
280 | printmca = show_f | |
281 | ||
282 | if (printmca != 0): | |
283 | if (first == 1): | |
284 | if (kern.ptrsize == 8): | |
285 | mca_string_format = "{0:4d} {1:4d} 0x{2:16x} " | |
286 | out_string += mca_string_format.format(x, y, sl) | |
287 | else: | |
288 | mca_string_format = "{0:4d} {1:4d} 0x{02:8x} " | |
289 | out_string += mca_string_format.format(x, y, sl) | |
290 | else: | |
291 | if (kern.ptrsize == 8): | |
292 | out_string += " " | |
293 | else: | |
294 | out_string += " " | |
295 | ||
296 | if (kern.ptrsize == 8): | |
297 | mca_string_format = "0x{0:16x} 0x{1:16x}" | |
298 | out_string += mca_string_format.format(mca, mca.mca_addr) | |
299 | else: | |
300 | mca_string_format = "0x{0:8x} 0x{1:8x}" | |
301 | out_string += mca_string_format.format(mca, mca.mca_addr) | |
302 | ||
303 | out_string += GetMbufMcaCtype(mca, 0) | |
304 | ||
305 | if (mca.mca_uflags & (MB_INUSE|MB_COMP_INUSE)): | |
306 | out_string += "active " | |
307 | else: | |
308 | out_string += " freed " | |
309 | if (first == 1): | |
310 | first = 0 | |
311 | out_string += "\n" | |
312 | total = total + 1 | |
313 | ||
314 | if (show_tr != 0): | |
315 | out_string += "Recent transaction for this buffer (thread: 0x" + hex(mca.mca_thread) + "):\n" | |
316 | cnt = 0 | |
317 | while (cnt < mca.mca_depth): | |
318 | kgm_pc = mca.mca_stack[int(cnt)] | |
319 | out_string += str(int(cnt) + 1) + " " | |
320 | out_string += GetPc(kgm_pc) | |
321 | cnt += 1 | |
322 | ||
323 | mca = mca.mca_next | |
324 | ||
325 | y += 1 | |
326 | if (slg.slg_slab[int(y)].sl_base == 0): | |
327 | stop = 1 | |
328 | x += 1 | |
329 | ||
330 | if (total and show_a and show_f): | |
331 | out_string += "total objects = " + str(int(total)) + "\n" | |
332 | out_string += "active/unfreed objects = " + str(int(total_a)) + "\n" | |
333 | out_string += "freed/in_cache objects = " + str(int(total_f)) + "\n" | |
334 | ||
335 | return out_string | |
336 | ||
337 | def GetMbufMcaCtype(mca, vopt): | |
338 | cp = mca.mca_cache | |
339 | mca_class = unsigned(cp.mc_private) | |
340 | csize = kern.globals.mbuf_table[mca_class].mtbl_stats.mbcl_size | |
341 | done = 0 | |
342 | out_string = " " | |
343 | if (csize == MSIZE): | |
344 | if (vopt): | |
345 | out_string += "M (mbuf) " | |
346 | else: | |
347 | out_string += "M " | |
348 | return out_string | |
349 | if (csize == MCLBYTES): | |
350 | if (vopt): | |
351 | out_string += "CL (2K cluster) " | |
352 | else: | |
353 | out_string += "CL " | |
354 | return out_string | |
355 | if (csize == NBPG): | |
356 | if (vopt): | |
357 | out_string += "BCL (4K cluster) " | |
358 | else: | |
359 | out_string += "BCL " | |
360 | return out_string | |
361 | if (csize == M16KCLBYTES): | |
362 | if (vopt): | |
363 | out_string += "JCL (16K cluster) " | |
364 | else: | |
365 | out_string += "JCL " | |
366 | return out_string | |
367 | ||
368 | if (csize == (MSIZE + MCLBYTES)): | |
369 | if (mca.mca_uflags & MB_SCVALID): | |
370 | if (mca.mca_uptr): | |
371 | out_string += "M+CL " | |
372 | if vopt: | |
373 | out_string += "(paired mbuf, 2K cluster) " | |
374 | else: | |
375 | out_string += "M-CL " | |
376 | if vopt: | |
377 | out_string += "(unpaired mbuf, 2K cluster) " | |
378 | else: | |
379 | if (mca.mca_uptr): | |
380 | out_string += "CL+M " | |
381 | if vopt: | |
382 | out_string += "(paired 2K cluster, mbuf) " | |
383 | else: | |
384 | out_string += "CL-M " | |
385 | if vopt: | |
386 | out_string += "(unpaired 2K cluster, mbuf) " | |
387 | return out_string | |
388 | ||
389 | if (csize == (MSIZE + NBPG)): | |
390 | if (mca.mca_uflags & MB_SCVALID): | |
391 | if (mca.mca_uptr): | |
392 | out_string += "M+BCL " | |
393 | if vopt: | |
394 | out_string += "(paired mbuf, 4K cluster) " | |
395 | else: | |
396 | out_string += "M-BCL " | |
397 | if vopt: | |
398 | out_string += "(unpaired mbuf, 4K cluster) " | |
399 | else: | |
400 | if (mca.mca_uptr): | |
401 | out_string += "BCL+M " | |
402 | if vopt: | |
403 | out_string += "(paired 4K cluster, mbuf) " | |
404 | else: | |
405 | out_string += "BCL-m " | |
406 | if vopt: | |
407 | out_string += "(unpaired 4K cluster, mbuf) " | |
408 | return out_string | |
409 | ||
410 | if (csize == (MSIZE + M16KCLBYTES)): | |
411 | if (mca.mca_uflags & MB_SCVALID): | |
412 | if (mca.mca_uptr): | |
413 | out_string += "M+BCL " | |
414 | if vopt: | |
415 | out_string += "(paired mbuf, 4K cluster) " | |
416 | else: | |
417 | out_string += "M-BCL " | |
418 | if vopt: | |
419 | out_string += "(unpaired mbuf, 4K cluster) " | |
420 | else: | |
421 | if (mca.mca_uptr): | |
422 | out_string += "BCL+M " | |
423 | if vopt: | |
424 | out_string += "(paired 4K cluster, mbuf) " | |
425 | else: | |
426 | out_string += "BCL-m " | |
427 | if vopt: | |
428 | out_string += "(unpaired 4K cluster, mbuf) " | |
429 | return out_string | |
430 | ||
431 | out_string += "unknown: " + cp.mc_name | |
432 | return out_string | |
433 | ||
434 | kgm_pkmod = 0 | |
435 | kgm_pkmodst = 0 | |
436 | kgm_pkmoden = 0 | |
437 | ||
438 | def GetPointerAsString(kgm_pc): | |
439 | if (kern.ptrsize == 8): | |
440 | pointer_format_string = "0x{0:<16x} " | |
441 | else: | |
442 | pointer_format_string = "0x{0:<8x} " | |
443 | return pointer_format_string.format(kgm_pc) | |
444 | ||
445 | def GetKmodAddrIntAsString(kgm_pc): | |
446 | global kgm_pkmod | |
447 | global kgm_pkmodst | |
448 | global kgm_pkmoden | |
449 | ||
450 | out_string = "" | |
451 | mh_execute_addr = int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16) | |
452 | ||
453 | out_string += GetPointerAsString(kgm_pc) | |
454 | if ((unsigned(kgm_pc) >= unsigned(kgm_pkmodst)) and (unsigned(kgm_pc) < unsigned(kgm_pkmoden))): | |
455 | kgm_off = kgm_pc - kgm_pkmodst | |
456 | out_string += "<" + str(Cast(kgm_pkmod, 'kmod_info_t *').name) + " + 0x" + str(kgm_off) + ">" | |
457 | else: | |
458 | kgm_kmodp = kern.globals.kmod | |
459 | if ((kern.arch == 'x86_64') and (long(kgm_pc) >= long(mh_execute_addr))): | |
460 | kgm_kmodp = 0 | |
461 | ||
462 | while kgm_kmodp: | |
463 | kgm_off = unsigned((kgm_pc - kgm_kmodp.address) & 0x00000000ffffffff) | |
464 | if ((long(kgm_kmodp.address) <= long(kgm_pc)) and (kgm_off) < unsigned(kgm_kmodp.size)): | |
465 | kgm_pkmod = kgm_kmodp | |
466 | kgm_pkmodst = unsigned(kgm_kmodp.address) | |
467 | kgm_pkmoden = unsigned(kgm_pkmodst + kgm_kmodp.size) | |
468 | kgm_kmodp = 0 | |
469 | else: | |
470 | kgm_kmodp = kgm_kmodp.next | |
471 | return out_string | |
472 | ||
473 | def GetPc(kgm_pc): | |
474 | out_string = "" | |
475 | mh_execute_addr = int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16) | |
476 | if (unsigned(kgm_pc) < unsigned(mh_execute_addr) or | |
477 | unsigned(kgm_pc) >= unsigned(kern.globals.vm_kernel_top)): | |
478 | out_string += GetKmodAddrIntAsString(kgm_pc) | |
479 | else: | |
480 | out_string += GetSourceInformationForAddress(int(kgm_pc)) | |
481 | return out_string + "\n" | |
482 | ||
483 | ||
484 | # Macro: mbuf_showactive | |
485 | @lldb_command('mbuf_showactive') | |
486 | def MbufShowActive(cmd_args=None): | |
487 | """ Print all active/in-use mbuf objects | |
488 | """ | |
489 | if cmd_args != None and len(cmd_args) > 0 : | |
490 | print GetMbufWalkAllSlabs(1, 0, cmd_args[0]) | |
491 | else: | |
492 | print GetMbufWalkAllSlabs(1, 0, 0) | |
493 | # EndMacro: mbuf_showactive | |
494 | ||
495 | ||
496 | # Macro: mbuf_showinactive | |
497 | @lldb_command('mbuf_showinactive') | |
498 | def MbufShowInactive(cmd_args=None): | |
499 | """ Print all freed/in-cache mbuf objects | |
500 | """ | |
501 | print GetMbufWalkAllSlabs(0, 1, 0) | |
502 | # EndMacro: mbuf_showinactive | |
503 | ||
504 | ||
505 | # Macro: mbuf_showmca | |
506 | @lldb_command('mbuf_showmca') | |
507 | def MbufShowMca(cmd_args=None): | |
508 | """ Print the contents of an mbuf mcache audit structure | |
509 | """ | |
510 | out_string = "" | |
511 | if cmd_args != None and len(cmd_args) > 0 : | |
512 | mca = kern.GetValueFromAddress(cmd_args[0], 'mcache_audit_t *') | |
513 | cp = mca.mca_cache | |
514 | out_string += "object type:\t" | |
515 | out_string += GetMbufMcaCtype(mca, 1) | |
516 | out_string += "\nControlling mcache :\t" + hex(mca.mca_cache) + " (" + str(cp.mc_name) + ")\n" | |
517 | if (mca.mca_uflags & MB_SCVALID): | |
518 | mbutl = cast(kern.globals.mbutl, 'union mbigcluster *') | |
519 | ix = (mca.mca_addr - mbutl) >> 12 | |
520 | clbase = mbutl + (sizeof(dereference(mbutl)) * ix) | |
521 | mclidx = (mca.mca_addr - clbase) >> 8 | |
522 | out_string += "mbuf obj :\t\t" + hex(mca.mca_addr) + "\n" | |
523 | out_string += "mbuf index :\t\t" + str(mclidx + 1) + " (out of 16) in cluster base " + hex(clbase) + "\n" | |
524 | if (int(mca.mca_uptr) != 0): | |
525 | peer_mca = cast(mca.mca_uptr, 'mcache_audit_t *') | |
526 | out_string += "paired cluster obj :\t" + hex(peer_mca.mca_addr) + " (mca " + hex(peer_mca) + ")\n" | |
527 | out_string += "saved contents :\t" + hex(mca.mca_contents) + " (" + str(int(mca.mca_contents_size)) + " bytes)\n" | |
528 | else: | |
529 | out_string += "cluster obj :\t\t" + hex(mca.mca_addr) + "\n" | |
530 | if (mca.mca_uptr != 0): | |
531 | peer_mca = cast(mca.mca_uptr, 'mcache_audit_t *') | |
532 | out_string += "paired mbuf obj :\t" + hex(peer_mca.mca_addr) + " (mca " + hex(peer_mca) + ")\n" | |
533 | ||
534 | out_string += "Recent transaction (tstamp " + str(unsigned(mca.mca_tstamp)) + ", thread " + hex(mca.mca_thread) + ") :\n" | |
535 | cnt = 0 | |
536 | while (cnt < mca.mca_depth): | |
537 | kgm_pc = mca.mca_stack[cnt] | |
538 | out_string += " " + str(cnt + 1) + ". " | |
539 | out_string += GetPc(kgm_pc) | |
540 | cnt += 1 | |
541 | ||
542 | if (mca.mca_pdepth > 0): | |
543 | out_string += "previous transaction (tstamp " + str(unsigned(mca.mca_ptstamp)) + ", thread " + hex(mca.mca_pthread) + "):\n" | |
544 | cnt = 0 | |
545 | ||
546 | while (cnt < mca.mca_pdepth): | |
547 | kgm_pc = mca.mca_pstack[cnt] | |
548 | out_string += " " + str(cnt + 1) + ". " | |
549 | out_string += GetPc(kgm_pc) | |
550 | cnt += 1 | |
551 | ||
552 | if (mca.mca_uflags & MB_SCVALID): | |
553 | msc = cast(mca.mca_contents, 'mcl_saved_contents_t *') | |
554 | msa = addressof(msc.sc_scratch) | |
555 | if (msa.msa_depth > 0): | |
556 | out_string += "Recent scratch transaction (tstamp " + str(unsigned(msa.msa_tstamp)) + ", thread " + hex(msa.msa_thread) + ") :\n" | |
557 | cnt = 0 | |
558 | while (cnt < msa.msa_depth): | |
559 | kgm_pc = msa.msa_stack[cnt] | |
560 | out_string += " " + str(cnt + 1) + ". " | |
561 | out_string += GetPc(kgm_pc) | |
562 | cnt += 1 | |
563 | ||
564 | if (msa.msa_pdepth > 0): | |
565 | out_string += "previous scratch transaction (tstamp " + msa.msa_ptstamp + ", thread " + msa.msa_pthread + "):\n" | |
566 | cnt = 0 | |
567 | while (cnt < msa.msa_pdepth): | |
568 | kgm_pc = msa.msa_pstack[cnt] | |
569 | out_string += " " + str(cnt + 1) + ". " | |
570 | out_string += GetPc(kgm_pc) | |
571 | cnt += 1 | |
572 | else : | |
573 | out_string += "Missing argument 0 in user function." | |
574 | ||
575 | print out_string | |
576 | # EndMacro: mbuf_showmca | |
577 | ||
578 | ||
579 | # Macro: mbuf_showall | |
580 | @lldb_command('mbuf_showall') | |
581 | def MbufShowAll(cmd_args=None): | |
582 | """ Print all mbuf objects | |
583 | """ | |
584 | print GetMbufWalkAllSlabs(1, 1, 0) | |
585 | # EndMacro: mbuf_showall | |
586 | ||
587 | # Macro: mbuf_countchain | |
588 | @lldb_command('mbuf_countchain') | |
589 | def MbufCountChain(cmd_args=None): | |
590 | """ Count the length of an mbuf chain | |
591 | """ | |
592 | if (cmd_args == None or len(cmd_args) == 0): | |
593 | print "Missing argument 0 in user function." | |
594 | return | |
595 | mp = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') | |
596 | ||
597 | pkt = 0 | |
598 | nxt = 0 | |
599 | ||
600 | while (mp): | |
601 | pkt = pkt + 1 | |
602 | mn = mp.m_hdr.mh_next | |
603 | while (mn): | |
604 | nxt = nxt + 1 | |
605 | mn = mn.m_hdr.mh_next | |
606 | ||
607 | mp = mp.m_hdr.mh_nextpkt | |
608 | ||
609 | if (((pkt + nxt) % 50) == 0): | |
610 | print " ..." + str(pkt_nxt) | |
611 | ||
612 | print "Total: " + str(pkt + nxt) + " (via m_next: " + str(nxt) + ")" | |
613 | # EndMacro: mbuf_countchain | |
614 | ||
615 | ||
616 | ||
617 | # Macro: mbuf_topleak | |
618 | @lldb_command('mbuf_topleak') | |
619 | def MbufTopLeak(cmd_args=None): | |
620 | """ Print the top suspected mbuf leakers | |
621 | """ | |
622 | topcnt = 0 | |
623 | if (int(len(cmd_args)) > 0 and int(cmd_args[0]) < 5): | |
624 | maxcnt = cmd_args[0] | |
625 | else: | |
626 | maxcnt = 5 | |
627 | while (topcnt < maxcnt): | |
628 | print GetMbufTraceLeak(kern.globals.mleak_top_trace[topcnt]) | |
629 | topcnt += 1 | |
630 | ||
631 | # EndMacro: mbuf_topleak | |
632 | ||
633 | def GetMbufTraceLeak(trace): | |
634 | out_string = "" | |
635 | if (trace.allocs != 0): | |
636 | out_string += hex(trace) + ":" + str(trace.allocs) + " outstanding allocs\n" | |
637 | out_string += "Backtrace saved " + str(trace.depth) + " deep\n" | |
638 | if (trace.depth != 0): | |
639 | cnt = 0 | |
640 | while (cnt < trace.depth): | |
641 | out_string += str(cnt + 1) + ": " | |
642 | out_string += GetPc(trace.addr[cnt]) | |
643 | out_string += "\n" | |
644 | cnt += 1 | |
645 | return out_string | |
646 | ||
647 | ||
648 | # Macro: mbuf_traceleak | |
649 | @lldb_command('mbuf_traceleak') | |
650 | def MbufTraceLeak(cmd_args=None): | |
651 | """ Print the leak information for a given leak address | |
652 | Given an mbuf leak trace (mtrace) structure address, print out the | |
653 | stored information with that trace | |
654 | syntax: (lldb) mbuf_traceleak <addr> | |
655 | """ | |
656 | if (cmd_args == None or len(cmd_args) == 0): | |
657 | print "Missing argument 0 in user function." | |
658 | return | |
659 | trace = kern.GetValueFromAddress(cmd_args[0], 'mtrace *') | |
660 | print GetMbufTraceLeak(trace) | |
661 | # EndMacro: mbuf_traceleak | |
662 | ||
663 | ||
664 | # Macro: mcache_walkobj | |
665 | @lldb_command('mcache_walkobj') | |
666 | def McacheWalkObject(cmd_args=None): | |
667 | """ Given a mcache object address, walk its obj_next pointer | |
668 | """ | |
669 | if (cmd_args == None or len(cmd_args) == 0): | |
670 | print "Missing argument 0 in user function." | |
671 | return | |
672 | out_string = "" | |
673 | p = kern.GetValueFromAddress(cmd_args[0], 'mcache_obj_t *') | |
674 | cnt = 1 | |
675 | total = 0 | |
676 | while (p): | |
677 | mcache_object_format = "{0:>4d}: 0x{1:>16x}" | |
678 | out_string += mcache_object_format.format(cnt, p) + "\n" | |
679 | p = p.obj_next | |
680 | cnt += 1 | |
681 | print out_string | |
682 | # EndMacro: mcache_walkobj | |
683 | ||
684 | # Macro: mcache_stat | |
685 | @lldb_command('mcache_stat') | |
686 | def McacheStat(cmd_args=None): | |
687 | """ Print all mcaches in the system. | |
688 | """ | |
689 | head = kern.globals.mcache_head | |
690 | out_string = "" | |
691 | mc = cast(head.lh_first, 'mcache *') | |
692 | if (kern.ptrsize == 8): | |
693 | mcache_stat_format_string = "{0:<24s} {1:>8s} {2:>20s} {3:>5s} {4:>5s} {5:>20s} {6:>30s} {7:>18s}" | |
694 | else: | |
695 | mcache_stat_format_string = "{0:<24s} {1:>8s} {2:>12s} {3:>5s} {4:>5s} {5:>12s} {6:>30s} {7:>18s}" | |
696 | ||
697 | if (kern.ptrsize == 8): | |
698 | 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}" | |
699 | else: | |
700 | 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}" | |
701 | ||
702 | out_string += mcache_stat_format_string.format("cache name", "cache state" , "cache addr", "buf size", "buf align", "backing zone", "wait nowait failed", "bufs incache") | |
703 | out_string += "\n" | |
704 | ||
705 | ncpu = int(kern.globals.ncpu) | |
706 | while mc != 0: | |
707 | bktsize = mc.mc_cpu[0].cc_bktsize | |
708 | cache_state = "" | |
709 | if (mc.mc_flags & MCF_NOCPUCACHE): | |
710 | cache_state = "disabled" | |
711 | else: | |
712 | if (bktsize == 0): | |
713 | cache_state = " offline" | |
714 | else: | |
715 | cache_state = " online" | |
716 | if (mc.mc_slab_zone != 0): | |
717 | backing_zone = mc.mc_slab_zone | |
718 | else: | |
719 | if (kern.ptrsize == 8): | |
720 | backing_zone = " custom" | |
721 | else: | |
722 | backing_zone = " custom" | |
723 | ||
724 | total = 0 | |
725 | total += mc.mc_full.bl_total * bktsize | |
726 | n = 0 | |
727 | while(n < ncpu): | |
728 | ccp = mc.mc_cpu[n] | |
729 | if (ccp.cc_objs > 0): | |
730 | total += ccp.cc_objs | |
731 | if (ccp.cc_pobjs > 0): | |
732 | total += ccp.cc_pobjs | |
733 | n += 1 | |
734 | ccp += 1 | |
735 | ||
736 | 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) | |
737 | out_string += "\n" | |
738 | mc = cast(mc.mc_list.le_next, 'mcache *') | |
739 | print out_string | |
740 | # EndMacro: mcache_stat | |
741 | ||
742 | # Macro: mcache_showcache | |
743 | @lldb_command('mcache_showcache') | |
744 | def McacheShowCache(cmd_args=None): | |
745 | """Display the number of objects in cache. | |
746 | """ | |
747 | out_string = "" | |
748 | cp = kern.GetValueFromAddress(cmd_args[0], 'mcache_t *') | |
749 | bktsize = cp.mc_cpu[0].cc_bktsize | |
750 | cnt = 0 | |
751 | total = 0 | |
752 | mcache_cache_format = "{0:<4d} {1:>8d} {2:>8d} {3:>8d}" | |
753 | out_string += "Showing cache " + str(cp.mc_name) + " :\n\n" | |
754 | out_string += " CPU cc_objs cc_pobjs total\n" | |
755 | out_string += "---- ------- -------- --------\n" | |
756 | ncpu = int(kern.globals.ncpu) | |
757 | while (cnt < ncpu): | |
758 | ccp = cp.mc_cpu[cnt] | |
759 | objs = ccp.cc_objs | |
760 | if (objs <= 0): | |
761 | objs = 0 | |
762 | pobjs = ccp.cc_pobjs | |
763 | if (pobjs <= 0): | |
764 | pobjs = 0 | |
765 | tot_cpu = objs + pobjs | |
766 | total += tot_cpu | |
767 | out_string += mcache_cache_format.format(cnt, objs, pobjs, tot_cpu) | |
768 | out_string += "\n" | |
769 | cnt += 1 | |
770 | ||
771 | out_string += " ========\n" | |
772 | out_string += " " + str(total) + "\n\n" | |
773 | total += cp.mc_full.bl_total * bktsize | |
774 | ||
775 | out_string += "Total # of full buckets (" + str(int(bktsize)) + " objs/bkt):\t" + str(int(cp.mc_full.bl_total)) +"\n" | |
776 | out_string += "Total # of objects cached:\t\t" + str(total) + "\n" | |
777 | print out_string | |
778 | # EndMacro: mcache_showcache |