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