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