xref: /xnu-8019.80.24/tools/lldbmacros/mbufs.py (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
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
6from xnu import *
7from utils import *
8
9from mbufdefines import *
10import xnudefines
11
12# Macro: mbuf_stat
13@lldb_command('mbuf_stat')
14def 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} {9: >8s}"
18    print hdr_format.format('class', 'total', 'cached', 'uncached', 'inuse', 'failed', 'waiter', 'notified', 'purge', 'max')
19    print hdr_format.format('name', 'objs', 'objs', 'objs/slabs', 'objs', 'alloc count', 'count', 'count', 'count', 'objs')
20    print hdr_format.format('-'*16, '-'*8, '-'*8, '-'*16, '-'*8, '-'*12, '-'*8, '-'*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} {10: >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                                  mbuf.mtbl_maxlimit)
43# EndMacro: mbuf_stat
44
45# Macro: mbuf_walkpkt
46@lldb_command('mbuf_walkpkt')
47def 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')
71def 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')
92def 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')
110def 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')
120def 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:016x} 0x{4:016x} {5:10d} {6:3d} {7:3d} {8:3d} {9:5d} {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:08x} 0x{4:08x} {5:10d} {6:3d} {7:3d} {8:3d} {9:5d} {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 and obj != 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, 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                    chunk_string_format = "                                            0x{0:16x} 0x{1:16x} {2:10d}\n"
182                else:
183                    chunk_string_format = "                            0x{0:8x} {1:4s} {2:10d}\n"
184
185                out_string += chunk_string_format.format(int(obj), int(mca), int(ts))
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')
194def 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    nslabspmb = int(((1 << MBSHIFT) >> unsigned(kern.globals.page_shift)))
210    while (x < unsigned(kern.globals.maxslabgrp)):
211        slg = slabstbl[x]
212        if (slg == 0):
213            out_string += slabs_table_blank_string_format.format(x+1)
214        else:
215            if (kern.ptrsize == 8):
216                slabs_table_string_format = "{0:>3d}: 0x{1:16x}  [ 0x{2:16x} - 0x{3:16x} ]\n"
217                out_string += slabs_table_string_format.format(x+1, slg, addressof(slg.slg_slab[0]), addressof(slg.slg_slab[nslabspmb-1]))
218            else:
219                slabs_table_string_format = "{0:>3d}: 0x{1:8x}  [ 0x{2:8x} - 0x{3:8x} ]\n"
220                out_string += slabs_table_string_format.format(x+1, slg, addressof(slg.slg_slab[0]), addressof(slg.slg_slab[nslabspmb-1]))
221
222        x += 1
223    print out_string
224# EndMacro: mbuf_slabstbl
225
226def GetMbufMcaPtr(m, cl):
227    pgshift = int(kern.globals.page_shift)
228    ix = int((m - Cast(kern.globals.mbutl, 'char *')) >> pgshift)
229    page_addr = (Cast(kern.globals.mbutl, 'char *') + (ix << pgshift))
230
231
232    if (int(cl) == 0):
233        midx = int((m - page_addr) >> 8)
234        mca = kern.globals.mclaudit[ix].cl_audit[midx]
235    elif (int(cl) == 1):
236        midx = int((m - page_addr) >> 11)
237        mca = kern.globals.mclaudit[ix].cl_audit[midx]
238    elif (int(cl) == 2):
239        midx = int((m - page_addr) >> 12)
240        mca = kern.globals.mclaudit[ix].cl_audit[midx]
241    else:
242        mca = kern.globals.mclaudit[ix].cl_audit[0]
243    return Cast(mca, 'mcache_audit_t *')
244
245def GetMbufSlab(m):
246    pgshift = int(kern.globals.page_shift)
247    gix = int((Cast(m, 'char *') - Cast(kern.globals.mbutl, 'char *')) >> MBSHIFT)
248    slabstbl = kern.globals.slabstbl
249    ix = int((Cast(m, 'char *') - Cast(slabstbl[gix].slg_slab[0].sl_base, 'char *')) >> pgshift)
250    return addressof(slabstbl[gix].slg_slab[ix])
251
252def GetMbufBuf2Mca(m):
253    sl = GetMbufSlab(m)
254    mca = GetMbufMcaPtr(m, sl.sl_class)
255    return str(mca)
256
257def GetMbufWalkAllSlabs(show_a, show_f, show_tr):
258    out_string = ""
259
260    kern.globals.slabstbl[0]
261
262    x = 0
263    total = 0
264    total_a = 0
265    total_f = 0
266
267    if (show_a and not(show_f)):
268        out_string += "Searching only for active... \n"
269    if (not(show_a) and show_f):
270        out_string += "Searching only for inactive... \n"
271    if (show_a and show_f):
272        out_string += "Displaying all... \n"
273
274    if (kern.ptrsize == 8):
275        show_mca_string_format = "{0:>4s} {1:>4s} {2:>16s} {3:>16s} {4:>16} {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    else:
278        show_mca_string_format = "{0:4s} {1:4s} {2:8s} {3:8s} {4:8} {5:12s} {6:12s}"
279        out_string += show_mca_string_format.format("slot", "idx", "slab address", "mca address", "obj address", "type", "allocation state\n")
280
281    nslabspmb = unsigned((1 << MBSHIFT) >> unsigned(kern.globals.page_shift))
282    while (x < unsigned(kern.globals.slabgrp)):
283        slg = kern.globals.slabstbl[x]
284        y = 0
285        while (y < nslabspmb):
286            sl = addressof(slg.slg_slab[y])
287            base = sl.sl_base
288            if (base == 0):
289                break
290
291            mca = GetMbufMcaPtr(base, sl.sl_class)
292            first = 1
293
294            while ((Cast(mca, 'int') != 0) and (unsigned(mca.mca_addr) != 0)):
295                printmca = 0
296                if (mca.mca_uflags & (MB_INUSE | MB_COMP_INUSE)):
297                    total_a = total_a + 1
298                    printmca = show_a
299                else:
300                    total_f = total_f + 1
301                    printmca = show_f
302
303                if (printmca != 0):
304                    if (first == 1):
305                        if (kern.ptrsize == 8):
306                            mca_string_format = "{0:4d} {1:4d} 0x{2:16x} "
307                            out_string += mca_string_format.format(x, y, sl)
308                        else:
309                            mca_string_format = "{0:4d} {1:4d} 0x{02:8x} "
310                            out_string += mca_string_format.format(x, y, sl)
311                    else:
312                        if (kern.ptrsize == 8):
313                            out_string += "                             "
314                        else:
315                            out_string += "                     "
316
317                    if (kern.ptrsize == 8):
318                        mca_string_format = "0x{0:16x} 0x{1:16x}"
319                        out_string += mca_string_format.format(mca, mca.mca_addr)
320                    else:
321                        mca_string_format = "0x{0:8x} 0x{1:8x}"
322                        out_string += mca_string_format.format(mca, mca.mca_addr)
323
324                    out_string += GetMbufMcaCtype(mca, 0)
325
326                    if (mca.mca_uflags & (MB_INUSE | MB_COMP_INUSE)):
327                        out_string += "active        "
328                    else:
329                        out_string += "       freed "
330                    if (show_tr > 1) and (mca.mca_uflags & MB_SCVALID):
331                        m = Cast(mca.mca_addr, 'struct mbuf *')
332                        mbuf_string = GetMbufFlags(m)
333                        mbuf_string += " " + GetMbufPktCrumbs(m)
334                        if (mbuf_string != ""):
335                            if (kern.ptrsize == 8):
336                                out_string += "\n                              " + mbuf_string
337                            else:
338                                out_string += "\n                      " + mbuf_string
339                    if (first == 1):
340                        first = 0
341
342                    out_string += "\n"
343                    total = total + 1
344
345                    if (show_tr != 0):
346                        if (mca.mca_next_trn == 0):
347                            trn = 1
348                        else:
349                            trn = 0
350                        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"
351                        cnt = 0
352                        while (cnt < mca.mca_trns[int(trn)].mca_depth):
353                            kgm_pc = mca.mca_trns[int(trn)].mca_stack[int(cnt)]
354                            out_string += str(int(cnt) + 1) + " "
355                            out_string += GetPc(kgm_pc)
356                            cnt += 1
357
358                    print out_string
359                    out_string = ""
360                mca = mca.mca_next
361
362            y += 1
363
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
373def GetMbufFlagsAsString(mbuf_flags):
374    flags = (unsigned)(mbuf_flags & 0xff)
375    out_string = ""
376    i = 0
377    num = 1
378    while num <= flags:
379        if flags & num:
380            out_string += mbuf_flags_strings[i] + ","
381        i += 1
382        num = num << 1
383    return rstrip(out_string, ",")
384
385def GetMbufFlags(m):
386    out_string = ""
387    if (m != 0):
388        out_string += "m_flags: " + hex(m.m_hdr.mh_flags)
389        if (m.m_hdr.mh_flags != 0):
390             out_string += " " + GetMbufFlagsAsString(m.m_hdr.mh_flags)
391    return out_string
392
393# Macro: mbuf_show_m_flags
394@lldb_command('mbuf_show_m_flags')
395def MbufShowFlags(cmd_args=None):
396    """ Return a formatted string description of the mbuf flags
397    """
398    m = kern.GetValueFromAddress(cmd_args[0], 'mbuf_t *')
399    print GetMbufFlags(m)
400
401def GetMbufPktCrumbsAsString(mbuf_crumbs):
402    flags = (unsigned)(mbuf_crumbs & 0xffff)
403    out_string = ""
404    i = 0
405    num = 1
406    while num <= flags:
407        if flags & num:
408            out_string += mbuf_pkt_crumb_strings[i] + ","
409        i += 1
410        num = num << 1
411    return rstrip(out_string, ",")
412
413def GetMbufPktCrumbs(m):
414    out_string = ""
415    if (m != 0):
416        if (m.m_hdr.mh_flags & M_PKTHDR) != 0:
417            flags = m.M_dat.MH.MH_pkthdr.pkt_crumbs
418            out_string += "pkt_crumbs: " + hex(flags)
419            if (flags != 0):
420                out_string += " " + GetMbufPktCrumbsAsString(flags)
421    return out_string
422
423# Macro: mbuf_showpktcrumbs
424@lldb_command('mbuf_showpktcrumbs')
425def MbufShowPktCrumbs(cmd_args=None):
426    """ Print the packet crumbs of an mbuf object mca
427    """
428    m = kern.GetValueFromAddress(cmd_args[0], 'mbuf_t *')
429    print GetMbufPktCrumbs(m)
430
431def GetMbufMcaCtype(mca, vopt):
432    cp = mca.mca_cache
433    mca_class = unsigned(cp.mc_private)
434    csize = unsigned(kern.globals.mbuf_table[mca_class].mtbl_stats.mbcl_size)
435    done = 0
436    out_string = "    "
437    if (csize == MSIZE):
438        if (vopt):
439            out_string += "M (mbuf) "
440        else:
441            out_string += "M     "
442        return out_string
443    if (csize == MCLBYTES):
444        if (vopt):
445            out_string += "CL (2K cluster) "
446        else:
447            out_string += "CL     "
448        return out_string
449    if (csize == MBIGCLBYTES):
450        if (vopt):
451            out_string += "BCL (4K cluster) "
452        else:
453            out_string += "BCL     "
454        return out_string
455    if (csize == M16KCLBYTES):
456        if (vopt):
457            out_string += "JCL (16K cluster) "
458        else:
459            out_string += "JCL     "
460        return out_string
461
462    if (csize == (MSIZE + MCLBYTES)):
463        if (mca.mca_uflags & MB_SCVALID):
464            if (mca.mca_uptr):
465                out_string += "M+CL  "
466                if vopt:
467                    out_string += "(paired mbuf, 2K cluster) "
468            else:
469                out_string += "M-CL  "
470                if vopt:
471                    out_string += "(unpaired mbuf, 2K cluster) "
472        else:
473            if (mca.mca_uptr):
474                out_string += "CL+M  "
475                if vopt:
476                    out_string += "(paired 2K cluster, mbuf) "
477            else:
478                out_string += "CL-M  "
479                if vopt:
480                    out_string += "(unpaired 2K cluster, mbuf) "
481        return out_string
482
483    if (csize == (MSIZE + MBIGCLBYTES)):
484        if (mca.mca_uflags & MB_SCVALID):
485            if (mca.mca_uptr):
486                out_string += "M+BCL  "
487                if vopt:
488                    out_string += "(paired mbuf, 4K cluster) "
489            else:
490                out_string += "M-BCL  "
491                if vopt:
492                    out_string += "(unpaired mbuf, 4K cluster) "
493        else:
494            if (mca.mca_uptr):
495                out_string += "BCL+M  "
496                if vopt:
497                    out_string += "(paired 4K cluster, mbuf) "
498            else:
499                out_string += "BCL-m  "
500                if vopt:
501                    out_string += "(unpaired 4K cluster, mbuf) "
502        return out_string
503
504    if (csize == (MSIZE + M16KCLBYTES)):
505        if (mca.mca_uflags & MB_SCVALID):
506            if (mca.mca_uptr):
507                out_string += "M+BCL  "
508                if vopt:
509                    out_string += "(paired mbuf, 4K cluster) "
510            else:
511                out_string += "M-BCL  "
512                if vopt:
513                    out_string += "(unpaired mbuf, 4K cluster) "
514        else:
515            if (mca.mca_uptr):
516                out_string += "BCL+M  "
517                if vopt:
518                    out_string += "(paired 4K cluster, mbuf) "
519            else:
520                out_string += "BCL-m  "
521                if vopt:
522                    out_string += "(unpaired 4K cluster, mbuf) "
523        return out_string
524
525    out_string += "unknown: " + cp.mc_name
526    return out_string
527
528
529def GetPointerAsString(kgm_pc):
530    if (kern.ptrsize == 8):
531        pointer_format_string = "0x{0:<16x} "
532    else:
533        pointer_format_string = "0x{0:<8x} "
534    return pointer_format_string.format(kgm_pc)
535
536def GetPc(kgm_pc):
537    out_string = GetSourceInformationForAddress(unsigned(kgm_pc)) + "\n"
538    return out_string
539
540
541# Macro: mbuf_showactive
542@lldb_command('mbuf_showactive')
543def MbufShowActive(cmd_args=None):
544    """ Print all active/in-use mbuf objects
545        Pass 1 to show the most transaction stack trace
546        Pass 2 to also display the mbuf flags and packet crumbs
547    """
548    if cmd_args:
549        print GetMbufWalkAllSlabs(1, 0, ArgumentStringToInt(cmd_args[0]))
550    else:
551        print GetMbufWalkAllSlabs(1, 0, 0)
552# EndMacro: mbuf_showactive
553
554
555# Macro: mbuf_showinactive
556@lldb_command('mbuf_showinactive')
557def MbufShowInactive(cmd_args=None):
558    """ Print all freed/in-cache mbuf objects
559    """
560    print GetMbufWalkAllSlabs(0, 1, 0)
561# EndMacro: mbuf_showinactive
562
563
564# Macro: mbuf_showmca
565@lldb_command('mbuf_showmca')
566def MbufShowMca(cmd_args=None):
567    """ Print the contents of an mbuf mcache audit structure
568    """
569    out_string = ""
570    pgshift = unsigned(kern.globals.page_shift)
571    if cmd_args:
572        mca = kern.GetValueFromAddress(cmd_args[0], 'mcache_audit_t *')
573        cp = mca.mca_cache
574        out_string += "object type:\t"
575        out_string += GetMbufMcaCtype(mca, 1)
576        out_string += "\nControlling mcache :\t" + hex(mca.mca_cache) + " (" + str(cp.mc_name) + ")\n"
577        if (mca.mca_uflags & MB_INUSE):
578            out_string += " inuse"
579        if (mca.mca_uflags & MB_COMP_INUSE):
580            out_string += " comp_inuse"
581        if (mca.mca_uflags & MB_SCVALID):
582            out_string += " scvalid"
583        out_string += "\n"
584        if (mca.mca_uflags & MB_SCVALID):
585            mbutl = Cast(kern.globals.mbutl, 'unsigned char *')
586            ix = (mca.mca_addr - mbutl) >> pgshift
587            clbase = mbutl + (ix << pgshift)
588            mclidx = (mca.mca_addr - clbase) >> 8
589            out_string += "mbuf obj :\t\t" + hex(mca.mca_addr) + "\n"
590            out_string += "mbuf index :\t\t" + str(mclidx + 1) + " (out of 16) in cluster base " + hex(clbase) + "\n"
591            if (int(mca.mca_uptr) != 0):
592                peer_mca = cast(mca.mca_uptr, 'mcache_audit_t *')
593                out_string += "paired cluster obj :\t" + hex(peer_mca.mca_addr) + " (mca " + hex(peer_mca) + ")\n"
594            out_string += "saved contents :\t" + hex(mca.mca_contents) + " (" + str(int(mca.mca_contents_size)) + " bytes)\n"
595        else:
596            out_string += "cluster obj :\t\t" + hex(mca.mca_addr) + "\n"
597            if (mca.mca_uptr != 0):
598                peer_mca = cast(mca.mca_uptr, 'mcache_audit_t *')
599                out_string += "paired mbuf obj :\t" + hex(peer_mca.mca_addr) + " (mca " + hex(peer_mca) + ")\n"
600
601        for idx in range(unsigned(kern.globals.mca_trn_max), 0, -1):
602                trn = (mca.mca_next_trn + idx - 1) % unsigned(kern.globals.mca_trn_max)
603                out_string += "transaction {:d} (tstamp {:d}, thread 0x{:x}):\n".format(trn, mca.mca_trns[trn].mca_tstamp, mca.mca_trns[trn].mca_thread)
604                cnt = 0
605                while (cnt < mca.mca_trns[trn].mca_depth):
606                    kgm_pc = mca.mca_trns[trn].mca_stack[cnt]
607                    out_string += "  " + str(cnt + 1) + ".  "
608                    out_string += GetPc(kgm_pc)
609                    cnt += 1
610
611        msc = cast(mca.mca_contents, 'mcl_saved_contents_t *')
612        msa = addressof(msc.sc_scratch)
613        if (mca.mca_uflags & MB_SCVALID):
614            if (msa.msa_depth > 0):
615                out_string += "Recent scratch transaction (tstamp {:d}, thread 0x{:x}):\n".format(msa.msa_tstamp, msa.msa_thread)
616                cnt = 0
617                while (cnt < msa.msa_depth):
618                    kgm_pc = msa.msa_stack[cnt]
619                    out_string += "  " + str(cnt + 1) + ".  "
620                    out_string += GetPc(kgm_pc)
621                    cnt += 1
622
623            if (msa.msa_pdepth > 0):
624                out_string += "previous scratch transaction (tstamp {:d}, thread 0x{:x}):\n".format(msa.msa_ptstamp, msa.msa_pthread)
625        if (msa):
626            cnt = 0
627            while (cnt < msa.msa_pdepth):
628                kgm_pc = msa.msa_pstack[cnt]
629                out_string += "  " + str(cnt + 1) + ".  "
630                out_string += GetPc(kgm_pc)
631                cnt += 1
632    else:
633        out_string += "Missing argument 0 in user function."
634
635    print out_string
636# EndMacro: mbuf_showmca
637
638
639# Macro: mbuf_showall
640@lldb_command('mbuf_showall')
641def MbufShowAll(cmd_args=None):
642    """ Print all mbuf objects
643    """
644    print GetMbufWalkAllSlabs(1, 1, 1)
645# EndMacro: mbuf_showall
646
647# Macro: mbuf_countchain
648@lldb_command('mbuf_countchain')
649def MbufCountChain(cmd_args=None):
650    """ Count the length of an mbuf chain
651    """
652    if not cmd_args:
653        raise ArgumentError("Missing argument 0 in user function.")
654
655    mp = kern.GetValueFromAddress(cmd_args[0], 'mbuf *')
656
657    pkt = 0
658    nxt = 0
659
660    while (mp):
661        pkt = pkt + 1
662        mn = mp.m_hdr.mh_next
663        while (mn):
664            nxt = nxt + 1
665            mn = mn.m_hdr.mh_next
666
667        mp = mp.m_hdr.mh_nextpkt
668
669        if (((pkt + nxt) % 50) == 0):
670            print " ..." + str(pkt_nxt)
671
672    print "Total: " + str(pkt + nxt) + " (via m_next: " + str(nxt) + ")"
673# EndMacro: mbuf_countchain
674
675
676# Macro: mbuf_topleak
677@lldb_command('mbuf_topleak')
678def MbufTopLeak(cmd_args=None):
679    """ Print the top suspected mbuf leakers
680    """
681    topcnt = 0
682    if (int(len(cmd_args)) > 0 and int(cmd_args[0]) < 5):
683        maxcnt = cmd_args[0]
684    else:
685        maxcnt = 5
686    while (topcnt < maxcnt):
687        print GetMbufTraceLeak(kern.globals.mleak_top_trace[topcnt])
688        topcnt += 1
689
690# EndMacro: mbuf_topleak
691
692def GetMbufTraceLeak(trace):
693    out_string = ""
694    if (trace.allocs != 0):
695        out_string += hex(trace) + ":" + str(trace.allocs) + " outstanding allocs\n"
696        out_string += "Backtrace saved " + str(trace.depth) + " deep\n"
697        if (trace.depth != 0):
698            cnt = 0
699            while (cnt < trace.depth):
700                out_string += str(cnt + 1) + ": "
701                out_string += GetPc(trace.addr[cnt])
702                out_string += "\n"
703                cnt += 1
704    return out_string
705
706@lldb_command('mbuf_largefailures')
707def MbufLargeFailures(cmd_args=None):
708    """ Print the largest allocation failures
709    """
710    topcnt = 0
711    if (int(len(cmd_args)) > 0 and int(cmd_args[0]) < 5):
712        maxcnt = cmd_args[0]
713    else:
714        maxcnt = 5
715    while (topcnt < maxcnt):
716        trace = kern.globals.mtracelarge_table[topcnt]
717        if (trace.size == 0):
718            topcnt += 1
719            continue
720        print str(trace.size)
721        if (trace.depth != 0):
722            cnt = 0
723            while (cnt < trace.depth):
724                print str(cnt + 1) + ": " + GetPc(trace.addr[cnt])
725                cnt += 1
726        topcnt += 1
727
728
729# Macro: mbuf_traceleak
730@lldb_command('mbuf_traceleak')
731def MbufTraceLeak(cmd_args=None):
732    """ Print the leak information for a given leak address
733        Given an mbuf leak trace (mtrace) structure address, print out the
734        stored information with that trace
735        syntax: (lldb) mbuf_traceleak <addr>
736    """
737    if not cmd_args:
738        raise ArgumentError("Missing argument 0 in user function.")
739
740    trace = kern.GetValueFromAddress(cmd_args[0], 'mtrace *')
741    print GetMbufTraceLeak(trace)
742# EndMacro: mbuf_traceleak
743
744
745# Macro: mcache_walkobj
746@lldb_command('mcache_walkobj')
747def McacheWalkObject(cmd_args=None):
748    """ Given a mcache object address, walk its obj_next pointer
749    """
750    if not cmd_args:
751        raise ArgumentError("Missing argument 0 in user function.")
752
753    out_string = ""
754    p = kern.GetValueFromAddress(cmd_args[0], 'mcache_obj_t *')
755    cnt = 1
756    total = 0
757    while (p):
758        mcache_object_format = "{0:>4d}: 0x{1:>16x}"
759        out_string += mcache_object_format.format(cnt, p) + "\n"
760        p = p.obj_next
761        cnt += 1
762    print out_string
763# EndMacro: mcache_walkobj
764
765# Macro: mcache_stat
766@lldb_command('mcache_stat')
767def McacheStat(cmd_args=None):
768    """ Print all mcaches in the system.
769    """
770    head = kern.globals.mcache_head
771    out_string = ""
772    mc = cast(head.lh_first, 'mcache *')
773    if (kern.ptrsize == 8):
774        mcache_stat_format_string = "{0:<24s} {1:>8s} {2:>20s} {3:>5s} {4:>5s} {5:>20s} {6:>30s} {7:>18s}"
775    else:
776        mcache_stat_format_string = "{0:<24s} {1:>8s} {2:>12s} {3:>5s} {4:>5s} {5:>12s} {6:>30s} {7:>18s}"
777
778    if (kern.ptrsize == 8):
779        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}"
780    else:
781        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}"
782
783    out_string += mcache_stat_format_string.format("cache name", "cache state", "cache addr", "buf size", "buf align", "backing zone", "wait     nowait     failed", "bufs incache")
784    out_string += "\n"
785
786    ncpu = int(kern.globals.ncpu)
787    while mc != 0:
788        bktsize = mc.mc_cpu[0].cc_bktsize
789        cache_state = ""
790        if (mc.mc_flags & MCF_NOCPUCACHE):
791            cache_state = "disabled"
792        else:
793            if (bktsize == 0):
794                cache_state = " offline"
795            else:
796                cache_state = " online"
797        if (mc.mc_slab_zone != 0):
798            backing_zone = mc.mc_slab_zone
799        else:
800            if (kern.ptrsize == 8):
801                backing_zone = "            custom"
802            else:
803                backing_zone = "    custom"
804
805        total = 0
806        total += mc.mc_full.bl_total * bktsize
807        n = 0
808        while(n < ncpu):
809            ccp = mc.mc_cpu[n]
810            if (ccp.cc_objs > 0):
811                total += ccp.cc_objs
812            if (ccp.cc_pobjs > 0):
813                total += ccp.cc_pobjs
814            n += 1
815            ccp += 1
816
817        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)
818        out_string += "\n"
819        mc = cast(mc.mc_list.le_next, 'mcache *')
820    print out_string
821# EndMacro: mcache_stat
822
823# Macro: mcache_showcache
824@lldb_command('mcache_showcache')
825def McacheShowCache(cmd_args=None):
826    """Display the number of objects in cache.
827    """
828    out_string = ""
829    cp = kern.GetValueFromAddress(cmd_args[0], 'mcache_t *')
830    bktsize = cp.mc_cpu[0].cc_bktsize
831    cnt = 0
832    total = 0
833    mcache_cache_format = "{0:<4d} {1:>8d} {2:>8d} {3:>8d}"
834    out_string += "Showing cache " + str(cp.mc_name) + " :\n\n"
835    out_string += " CPU  cc_objs cc_pobjs    total\n"
836    out_string += "----  ------- -------- --------\n"
837    ncpu = int(kern.globals.ncpu)
838    while (cnt < ncpu):
839        ccp = cp.mc_cpu[cnt]
840        objs = ccp.cc_objs
841        if (objs <= 0):
842            objs = 0
843        pobjs = ccp.cc_pobjs
844        if (pobjs <= 0):
845            pobjs = 0
846        tot_cpu = objs + pobjs
847        total += tot_cpu
848        out_string += mcache_cache_format.format(cnt, objs, pobjs, tot_cpu)
849        out_string += "\n"
850        cnt += 1
851
852    out_string += "                       ========\n"
853    out_string += "                           " + str(total) + "\n\n"
854    total += cp.mc_full.bl_total * bktsize
855
856    out_string += "Total # of full buckets (" + str(int(bktsize)) + " objs/bkt):\t" + str(int(cp.mc_full.bl_total)) + "\n"
857    out_string += "Total # of objects cached:\t\t" + str(total) + "\n"
858    print out_string
859# EndMacro: mcache_showcache
860
861# Macro: mbuf_wdlog
862@lldb_command('mbuf_wdlog')
863def McacheShowWatchdogLog(cmd_args=None):
864    """Display the watchdog log
865    """
866    lldb_run_command('settings set max-string-summary-length 4096')
867    print('%s' % lldb_run_command('p/s mbwdog_logging').replace("\\n","\n"))
868# EndMacro: mbuf_wdlog
869