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