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}"
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')
47def 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')
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 (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')
113def 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')
123def 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')
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    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
226def 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
235def 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
337def 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
434kgm_pkmod = 0
435kgm_pkmodst = 0
436kgm_pkmoden = 0
437
438def 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
445def 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
473def 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')
486def 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')
498def 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')
507def 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')
581def 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')
589def 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')
619def 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
633def 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')
650def 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')
666def 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')
686def 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')
744def 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
779