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_walk_mleak_traces 46@lldb_command('mbuf_walk_mleak_traces') 47def 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 71# Macro: mbuf_walkpkt 72@lldb_command('mbuf_walkpkt') 73def MbufWalkPacket(cmd_args=None): 74 """ Walk the mbuf packet chain (m_nextpkt) 75 """ 76 if not cmd_args: 77 raise ArgumentError("Missing argument 0 in user function.") 78 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') 97def 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') 118def MbufBuf2Slab(cmd_args=None): 119 """ Given an mbuf object, find its corresponding slab address 120 """ 121 if not cmd_args: 122 raise ArgumentError("Missing argument 0 in user function.") 123 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') 139def 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') 149def MbufSlabs(cmd_args=None): 150 """ Print all slabs in the group 151 """ 152 153 out_string = "" 154 if not cmd_args: 155 raise ArgumentError("Invalid arguments passed.") 156 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) 179 mclidx = (obj - clbase) >> 8 180 mca = kern.globals.mclaudit[int(ix)].cl_audit[int(mclidx)] 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 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) 209 mclidx = (obj - clbase) >> 8 210 mca = kern.globals.mclaudit[int(ix)].cl_audit[int(mclidx)] 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 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') 226def 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 258def 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) 263 mclidx = (m - clbase) >> 8 264 mca = kern.globals.mclaudit[int(ix)].cl_audit[int(mclidx)] 265 return str(mca) 266 267def GetMbufWalkAllSlabs(show_a, show_f, show_tr): 268 out_string = "" 269 270 kern.globals.slabstbl[0] 271 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) 301 mclidx = (base - clbase) >> 8 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 307 if (mca.mca_uflags & (MB_INUSE | MB_COMP_INUSE)): 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 337 if (mca.mca_uflags & (MB_INUSE | MB_COMP_INUSE)): 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): 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" 350 cnt = 0 351 while (cnt < mca.mca_trns[int(trn)].mca_depth): 352 kgm_pc = mca.mca_trns[int(trn)].mca_stack[int(cnt)] 353 out_string += str(int(cnt) + 1) + " " 354 out_string += GetPc(kgm_pc) 355 cnt += 1 356 357 print out_string 358 out_string = "" 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 373def GetMbufMcaCtype(mca, vopt): 374 cp = mca.mca_cache 375 mca_class = unsigned(cp.mc_private) 376 csize = unsigned(kern.globals.mbuf_table[mca_class].mtbl_stats.mbcl_size) 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 " 433 if vopt: 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 469 470kgm_pkmod = 0 471kgm_pkmodst = 0 472kgm_pkmoden = 0 473 474def 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 481def 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 509def 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) 512 if (unsigned(kgm_pc) < unsigned(mh_execute_addr) or unsigned(kgm_pc) >= unsigned(kern.globals.vm_kernel_top)): 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') 521def MbufShowActive(cmd_args=None): 522 """ Print all active/in-use mbuf objects 523 """ 524 if cmd_args: 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') 533def 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') 542def MbufShowMca(cmd_args=None): 543 """ Print the contents of an mbuf mcache audit structure 544 """ 545 out_string = "" 546 if cmd_args: 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" 568 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) 581 if (mca.mca_uflags & MB_SCVALID): 582 if (msa.msa_depth > 0): 583 out_string += "Recent scratch transaction (tstamp {:d}, thread 0x{:x}):\n".format(msa.msa_tstamp, msa.msa_thread) 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): 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: 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') 609def MbufShowAll(cmd_args=None): 610 """ Print all mbuf objects 611 """ 612 print GetMbufWalkAllSlabs(1, 1, 0) 613# EndMacro: mbuf_showall 614 615# Macro: mbuf_countchain 616@lldb_command('mbuf_countchain') 617def MbufCountChain(cmd_args=None): 618 """ Count the length of an mbuf chain 619 """ 620 if not cmd_args: 621 raise ArgumentError("Missing argument 0 in user function.") 622 623 mp = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') 624 625 pkt = 0 626 nxt = 0 627 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') 647def 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 661def 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') 678def 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 """ 684 if not cmd_args: 685 raise ArgumentError("Missing argument 0 in user function.") 686 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') 694def McacheWalkObject(cmd_args=None): 695 """ Given a mcache object address, walk its obj_next pointer 696 """ 697 if not cmd_args: 698 raise ArgumentError("Missing argument 0 in user function.") 699 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') 714def 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}" 724 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}" 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") 731 out_string += "\n" 732 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" 751 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') 772def 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 803 out_string += "Total # of full buckets (" + str(int(bktsize)) + " objs/bkt):\t" + str(int(cp.mc_full.bl_total)) + "\n" 804 out_string += "Total # of objects cached:\t\t" + str(total) + "\n" 805 print out_string 806# EndMacro: mcache_showcache 807