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""" 5from __future__ import absolute_import, division, print_function 6 7from builtins import hex 8from builtins import range 9 10from xnu import * 11from utils import * 12 13from mbufdefines import * 14import xnudefines 15import kmemory 16 17def MbufZoneByName(name): 18 for i in range(1, int(kern.GetGlobalVariable('num_zones'))): 19 z = addressof(kern.globals.zone_array[i]) 20 zs = addressof(kern.globals.zone_security_array[i]) 21 if ZoneName(z, zs) == name: 22 return (z, zs) 23 return None 24 25# Macro: mbuf_stat 26@lldb_command('mbuf_stat') 27def MBufStat(cmd_args=None): 28 """ Print extended mbuf allocator statistics. 29 """ 30 hdr_format = "{0: <16s} {1: >8s} {2: >8s} {3: ^16s} {4: >8s} {5: >12s} {6: >8s} {7: >8s} {8: >8s} {9: >8s}" 31 print(hdr_format.format('class', 'total', 'cached', 'uncached', 'inuse', 'failed', 'waiter', 'notified', 'purge', 'max')) 32 print(hdr_format.format('name', 'objs', 'objs', 'objs/slabs', 'objs', 'alloc count', 'count', 'count', 'count', 'objs')) 33 print(hdr_format.format('-'*16, '-'*8, '-'*8, '-'*16, '-'*8, '-'*12, '-'*8, '-'*8, '-'*8, '-'*8)) 34 entry_format = "{0: <16s} {1: >8d} {2: >8d} {3:>7d} / {4:<6d} {5: >8d} {6: >12d} {7: >8d} {8: >8d} {9: >8d} {10: >8d}" 35 num_items = sizeof(kern.globals.mbuf_table) // sizeof(kern.globals.mbuf_table[0]) 36 ncpus = int(kern.globals.ncpu) 37 mb_uses_mcache = int(kern.globals.mb_uses_mcache) 38 for i in range(num_items): 39 mbuf = kern.globals.mbuf_table[i] 40 mcs = Cast(mbuf.mtbl_stats, 'mb_class_stat_t *') 41 if mb_uses_mcache == 0: 42 cname = str(mcs.mbcl_cname) 43 if cname == "mbuf": 44 zone = MbufZoneByName("mbuf") 45 elif cname == "cl": 46 zone = MbufZoneByName("data.mbuf.cluster.2k") 47 elif cname == "bigcl": 48 zone = MbufZoneByName("data.mbuf.cluster.4k") 49 elif cname == "16kcl": 50 zone = MbufZoneByName("data.mbuf.cluster.16k") 51 elif cname == "mbuf_cl": 52 zone = MbufZoneByName("mbuf.composite.2k") 53 elif cname == "mbuf_bigcl": 54 zone = MbufZoneByName("mbuf.composite.4k") 55 elif cname == "mbuf_16kcl": 56 zone = MbufZoneByName("mbuf.composite.16k") 57 zone_stats = GetZone(zone[0], zone[1], [], []) 58 print(entry_format.format(cname, 59 int(zone_stats['size'] / mcs.mbcl_size), 60 zone_stats['cache_element_count'], 61 zone_stats['free_element_count'], 62 0, 63 int(zone_stats['used_size'] / mcs.mbcl_size), 64 zone_stats['alloc_fail_count'], 65 0, 0, 0, 66 mbuf.mtbl_maxlimit)) 67 68 else: 69 mc = mbuf.mtbl_cache 70 total = 0 71 total += int(mc.mc_full.bl_total) * int(mc.mc_cpu[0].cc_bktsize) 72 ccp_arr = mc.mc_cpu 73 for i in range(ncpus): 74 ccp = ccp_arr[i] 75 if int(ccp.cc_objs) > 0: 76 total += int(ccp.cc_objs) 77 if int(ccp.cc_pobjs) > 0: 78 total += int(ccp.cc_pobjs) 79 print(entry_format.format(mcs.mbcl_cname, mcs.mbcl_total, total, 80 mcs.mbcl_infree, mcs.mbcl_slab_cnt, 81 (mcs.mbcl_total - total - mcs.mbcl_infree), 82 mcs.mbcl_fail_cnt, mbuf.mtbl_cache.mc_waiter_cnt, 83 mcs.mbcl_notified, mcs.mbcl_purge_cnt, 84 mbuf.mtbl_maxlimit)) 85# EndMacro: mbuf_stat 86 87def DumpMbufData(mp, count): 88 if kern.globals.mb_uses_mcache == 1: 89 mdata = mp.m_hdr.mh_data 90 mlen = mp.m_hdr.mh_len 91 flags = mp.m_hdr.mh_flags 92 if flags & M_EXT: 93 mdata = mp.M_dat.MH.MH_dat.MH_ext.ext_buf 94 else: 95 mdata = mp.M_hdr_common.M_hdr.mh_data 96 mlen = mp.M_hdr_common.M_hdr.mh_len 97 flags = mp.M_hdr_common.M_hdr.mh_flags 98 if flags & M_EXT: 99 mdata = mp.M_hdr_common.M_ext.ext_buf 100 if (count > mlen): 101 count = mlen 102 cmd = "memory read -force -size 1 -count {0:d} 0x{1:x}".format(count, mdata) 103 print(lldb_run_command(cmd)) 104 105def DecodeMbufData(mp, decode_as="ether"): 106 import scapy.all 107 err = lldb.SBError() 108 while True: 109 full_buf = b'' 110 while True: 111 if kern.globals.mb_uses_mcache == 1: 112 mdata = mp.m_hdr.mh_data 113 mlen = mp.m_hdr.mh_len 114 flags = mp.m_hdr.mh_flags 115 if flags & M_EXT: 116 mdata = mp.M_dat.MH.MH_dat.MH_ext.ext_buf 117 mnext = mp.m_hdr.mh_next 118 else: 119 mdata = mp.M_hdr_common.M_hdr.mh_data 120 mlen = mp.M_hdr_common.M_hdr.mh_len 121 flags = mp.M_hdr_common.M_hdr.mh_flags 122 if flags & M_EXT: 123 mdata = mp.M_hdr_common.M_ext.ext_buf 124 mnext = mp.M_hdr_common.M_hdr.mh_next 125 126 addr = mdata.GetSBValue().GetValueAsAddress() 127 buf = LazyTarget.GetProcess().ReadMemory(addr, mlen, err) 128 full_buf += buf 129 if mnext == 0: 130 try: 131 if decode_as == "ether": 132 pkt = scapy.layers.l2.Ether(full_buf) 133 elif decode_as == "ip": 134 pkt = scapy.layers.inet.IP(full_buf) 135 elif decode_as == "ip6": 136 pkt = scapy.layers.inet6.IPv6(full_buf) 137 elif decode_as == "tcp": 138 pkt = scapy.layers.inet.TCP(full_buf) 139 elif decode_as == "udp": 140 pkt = scapy.layers.inet.UDP(full_buf) 141 else: 142 print("invalid decoder" + decode_as) 143 return 144 pkt.show() 145 break 146 except KeyboardInterrupt: 147 raise KeyboardInterrupt 148 except: 149 break 150 mp = mnext 151 if kern.globals.mb_uses_mcache == 1: 152 mp = mp.m_hdr.mh_nextpkt 153 else: 154 mp = mp.M_hdr_common.M_hdr.mh_nextpkt 155 if mp is None: 156 break 157 158 159# Macro: mbuf_decode 160@lldb_command('mbuf_decode', '') 161def MbufDecode(cmd_args=None, cmd_options={}): 162 """Decode an mbuf using scapy. 163 Usage: mbuf_decode <mbuf address> 164 """ 165 if cmd_args == None or len(cmd_args) < 1: 166 print("usage: mbuf_decode <address> [decode_as]") 167 return 168 mp = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') 169 if len(cmd_args) > 1: 170 decode_as = cmd_args[1] 171 DecodeMbufData(mp, decode_as) 172 else: 173 DecodeMbufData(mp) 174# EndMacro: mbuf_decode 175 176# Macro: mbuf_dumpdata 177@lldb_command('mbuf_dumpdata', 'C:') 178def MbufDumpData(cmd_args=None, cmd_options={}): 179 """Dump the mbuf data 180 Usage: mbuf_dumpdata <mbuf address> [-C <count>] 181 """ 182 if cmd_args == None or len(cmd_args) < 1: 183 print(MbufDumpData.__doc__) 184 return 185 mp = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') 186 if kern.globals.mb_uses_mcache == 1: 187 mdata = mp.m_hdr.mh_data 188 mhlen = mp.m_hdr.mh_len 189 else: 190 mdata = mp.M_hdr_common.M_hdr.mh_data 191 mhlen = mp.M_hdr_common.M_hdr.mh_len 192 mlen = 0 193 if "-C" in cmd_options: 194 mlen = ArgumentStringToInt(cmd_options["-C"]) 195 if (mlen > mhlen): 196 mlen = mhlen 197 else: 198 mlen = mhlen 199 DumpMbufData(mp, mlen) 200# EndMacro: mbuf_dumpdata 201 202def ShowMbuf(prefix, mp, count, total, dump_data_len): 203 out_string = "" 204 mca = "" 205 if kern.globals.mb_uses_mcache == 1: 206 mhlen = mp.m_hdr.mh_len 207 mhtype = mp.m_hdr.mh_type 208 mhflags = mp.m_hdr.mh_flags 209 if kern.globals.mclaudit != 0: 210 mca += GetMbufBuf2Mca(mp) + ", " 211 else: 212 mhlen = mp.M_hdr_common.M_hdr.mh_len 213 mhtype = mp.M_hdr_common.M_hdr.mh_type 214 mhflags = mp.M_hdr_common.M_hdr.mh_flags 215 mbuf_walk_format = "{0:s}{1:d} 0x{2:x} [len {3:d}, type {4:d}, " 216 out_string += mbuf_walk_format.format(prefix, count[0], mp, mhlen, mhtype) 217 out_string += "flags " + GetMbufFlagsAsString(mhflags) + ", " 218 if (mhflags & M_PKTHDR): 219 out_string += GetMbufPktCrumbs(mp) + ", " 220 if (mca != ""): 221 out_string += mca + ", " 222 total[0] = total[0] + mhlen 223 out_string += "total " + str(total[0]) + "]" 224 print(out_string) 225 if (dump_data_len > 0): 226 DumpMbufData(mp, dump_data_len) 227 228def WalkMufNext(prefix, mp, count, total, dump_data_len): 229 remaining_len = dump_data_len 230 while (mp): 231 if kern.globals.mb_uses_mcache == 1: 232 mhlen = mp.m_hdr.mh_len 233 mhnext = mp.m_hdr.mh_next 234 else: 235 mhlen = mp.M_hdr_common.M_hdr.mh_len 236 mhnext = mp.M_hdr_common.M_hdr.mh_next 237 count[0] += 1 238 ShowMbuf(prefix, mp, count, total, remaining_len) 239 if (remaining_len > mhlen): 240 remaining_len -= mhlen 241 else: 242 remaining_len = 0 243 mp = mhnext 244 245# Macro: mbuf_walkpkt 246@lldb_command('mbuf_walkpkt', 'C:') 247def MbufWalkPacket(cmd_args=None, cmd_options={}): 248 """ Walk the mbuf packet chain (m_nextpkt) 249 Usage: mbuf_walkpkt <mbuf address> [-C <count>] 250 """ 251 if not cmd_args: 252 raise ArgumentError("Missing argument 0 in user function.") 253 mp = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') 254 255 dump_data_len = 0 256 if "-C" in cmd_options: 257 dump_data_len = ArgumentStringToInt(cmd_options["-C"]) 258 259 count_packet = 0 260 count_mbuf = 0 261 total_len = 0 262 263 while (mp): 264 count_packet += 1 265 prefix = "{0:d}.".format(count_packet) 266 count = [0] 267 total = [0] 268 WalkMufNext(prefix, mp, count, total, dump_data_len) 269 count_mbuf += count[0] 270 total_len += total[0] 271 if kern.globals.mb_uses_mcache == 1: 272 mp = mp.m_hdr.mh_nextpkt 273 else: 274 mp = mp.M_hdr_common.M_hdr.mh_next 275 out_string = "Total packets: {0:d} mbufs: {1:d} length: {2:d} ".format(count_packet, count_mbuf, total_len) 276 print(out_string) 277# EndMacro: mbuf_walkpkt 278 279# Macro: mbuf_walk 280@lldb_command('mbuf_walk', 'C:') 281def MbufWalk(cmd_args=None, cmd_options={}): 282 """ Walk the mbuf chain (m_next) 283 Usage: mbuf_walk <mbuf address> [-C <count>] 284 """ 285 if not cmd_args: 286 raise ArgumentError("Missing argument 0 in user function.") 287 mp = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') 288 289 dump_data_len = 0 290 if "-C" in cmd_options: 291 dump_data_len = ArgumentStringToInt(cmd_options["-C"]) 292 293 count = [0] 294 total = [0] 295 prefix = "" 296 WalkMufNext(prefix, mp, count, total, dump_data_len) 297# EndMacro: mbuf_walk 298 299# Macro: mbuf_buf2slab 300@lldb_command('mbuf_buf2slab') 301def MbufBuf2Slab(cmd_args=None): 302 """ Given an mbuf object, find its corresponding slab address 303 """ 304 if not cmd_args: 305 raise ArgumentError("Missing argument 0 in user function.") 306 307 if int(kern.globals.mb_uses_mcache) == 0: 308 print("mcache is disabled, use kasan whatis") 309 return 310 311 m = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') 312 slab = GetMbufSlab(m) 313 if (kern.ptrsize == 8): 314 mbuf_slab_format = "0x{0:<16x}" 315 print(mbuf_slab_format.format(slab)) 316 else: 317 mbuf_slab_format = "0x{0:<8x}" 318 print(mbuf_slab_format.format(slab)) 319# EndMacro: mbuf_buf2slab 320 321# Macro: mbuf_buf2mca 322@lldb_command('mbuf_buf2mca') 323def MbufBuf2Mca(cmd_args=None): 324 """ Find the mcache audit structure of the corresponding mbuf 325 """ 326 if int(kern.globals.mb_uses_mcache) == 0: 327 print("mcache is disabled, use kasan whatis") 328 return 329 330 m = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') 331 print(GetMbufBuf2Mca(m)) 332 return 333# EndMacro: mbuf_buf2mca 334 335# Macro: mbuf_slabs 336@lldb_command('mbuf_slabs') 337def MbufSlabs(cmd_args=None): 338 """ Print all slabs in the group 339 """ 340 341 if int(kern.globals.mb_uses_mcache) == 0: 342 print("mcache is disabled, use kasan whatis or zprint") 343 return 344 345 out_string = "" 346 if not cmd_args: 347 raise ArgumentError("Invalid arguments passed.") 348 349 slg = kern.GetValueFromAddress(cmd_args[0], 'mcl_slabg_t *') 350 x = 0 351 352 if (kern.ptrsize == 8): 353 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} " 354 out_string += "slot slab next obj mca tstamp C R N size flags\n" 355 out_string += "----- ------------------ ------------------ ------------------ ------------------ ---------- --- --- --- ------ -----\n" 356 else: 357 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} " 358 out_string += "slot slab next obj mca tstamp C R N size flags\n" 359 out_string += "----- ---------- ---------- ---------- ---------- ---------- --- --- --- ------ -----\n" 360 361 mbutl = cast(kern.globals.mbutl, 'unsigned char *') 362 nslabspmb = int((1 << MBSHIFT) >> unsigned(kern.globals.page_shift)) 363 while x < nslabspmb: 364 sl = addressof(slg.slg_slab[x]) 365 mca = 0 366 obj = sl.sl_base 367 ts = 0 368 369 if (kern.globals.mclaudit != 0 and obj != 0): 370 mca = GetMbufMcaPtr(obj, sl.sl_class) 371 trn = (mca.mca_next_trn + unsigned(kern.globals.mca_trn_max) - 1) % unsigned(kern.globals.mca_trn_max) 372 ts = mca.mca_trns[trn].mca_tstamp 373 374 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)) 375 376 if (sl.sl_flags != 0): 377 out_string += "<" 378 if sl.sl_flags & SLF_MAPPED: 379 out_string += "mapped" 380 if sl.sl_flags & SLF_PARTIAL: 381 out_string += ",partial" 382 if sl.sl_flags & SLF_DETACHED: 383 out_string += ",detached" 384 out_string += ">" 385 out_string += "\n" 386 387 if sl.sl_chunks > 1: 388 z = 1 389 c = sl.sl_len // sl.sl_chunks 390 391 while z < sl.sl_chunks: 392 obj = sl.sl_base + (c * z) 393 mca = 0 394 ts = 0 395 396 if (kern.globals.mclaudit != 0 ): 397 mca = GetMbufMcaPtr(obj, sl.sl_class) 398 trn = (mca.mca_next_trn + unsigned(kern.globals.mca_trn_max) - 1) % unsigned(kern.globals.mca_trn_max) 399 ts = mca.mca_trns[trn].mca_tstamp 400 401 if (kern.ptrsize == 8): 402 chunk_string_format = " 0x{0:16x} 0x{1:16x} {2:10d}\n" 403 else: 404 chunk_string_format = " 0x{0:8x} {1:4s} {2:10d}\n" 405 406 out_string += chunk_string_format.format(int(obj), int(mca), int(ts)) 407 408 z += 1 409 x += 1 410 print(out_string) 411# EndMacro: mbuf_slabs 412 413# Macro: mbuf_slabstbl 414@lldb_command('mbuf_slabstbl') 415def MbufSlabsTbl(cmd_args=None): 416 """ Print slabs table 417 """ 418 out_string = "" 419 x = 0 420 421 if int(kern.globals.mb_uses_mcache) == 0: 422 print("mcache is disabled, use kasan whatis or zprint") 423 return 424 425 if (kern.ptrsize == 8): 426 out_string += "slot slabg slabs range\n" 427 out_string += "---- ------------------ -------------------------------------------\n" 428 else: 429 out_string += "slot slabg slabs range\n" 430 out_string += "---- ---------- ---------------------------\n" 431 432 slabstbl = kern.globals.slabstbl 433 slabs_table_blank_string_format = "{0:>3d}: - \n" 434 nslabspmb = int(((1 << MBSHIFT) >> unsigned(kern.globals.page_shift))) 435 while (x < unsigned(kern.globals.maxslabgrp)): 436 slg = slabstbl[x] 437 if (slg == 0): 438 out_string += slabs_table_blank_string_format.format(x+1) 439 else: 440 if (kern.ptrsize == 8): 441 slabs_table_string_format = "{0:>3d}: 0x{1:16x} [ 0x{2:16x} - 0x{3:16x} ]\n" 442 out_string += slabs_table_string_format.format(x+1, slg, addressof(slg.slg_slab[0]), addressof(slg.slg_slab[nslabspmb-1])) 443 else: 444 slabs_table_string_format = "{0:>3d}: 0x{1:8x} [ 0x{2:8x} - 0x{3:8x} ]\n" 445 out_string += slabs_table_string_format.format(x+1, slg, addressof(slg.slg_slab[0]), addressof(slg.slg_slab[nslabspmb-1])) 446 447 x += 1 448 print(out_string) 449# EndMacro: mbuf_slabstbl 450 451def MbufDecode(mbuf, decode_pkt): 452 # Ignore free'd mbufs. 453 if kern.globals.mb_uses_mcache == 1: 454 mhlen = mbuf.m_hdr.mh_len 455 mhtype = mbuf.m_hdr.mh_type 456 mhflags = mbuf.m_hdr.mh_flags 457 else: 458 mhlen = mbuf.M_hdr_common.M_hdr.mh_len 459 mhtype = mbuf.M_hdr_common.M_hdr.mh_type 460 mhflags = mbuf.M_hdr_common.M_hdr.mh_flags 461 if mhtype == 0: 462 return 463 flags = int(mhflags) 464 length = int(mhlen) 465 if length < 20 or length > 8 * 1024: 466 # Likely not a packet. 467 return 468 out_string = "mbuf found @ 0x{0:x}, length {1:d}, {2:s}, {3:s}".format(mbuf, length, GetMbufFlags(mbuf), GetMbufPktCrumbs(mbuf)) 469 print(out_string) 470 if flags & M_PKTHDR: 471 if kern.globals.mb_uses_mcache == 1: 472 rcvif = mbuf.M_dat.MH.MH_pkthdr.rcvif 473 else: 474 rcvif = mbuf.M_hdr_common.M_pkthdr.rcvif 475 if rcvif != 0: 476 try: 477 print("receive interface " + rcvif.if_xname) 478 except ValueError: 479 pass 480 if decode_pkt: 481 DecodeMbufData(mbuf) 482 483 484# Macro: mbuf_walk_slabs 485@lldb_command('mbuf_walk_slabs') 486def MbufWalkSlabs(cmd_args=None): 487 """ 488 Walks the mbuf slabs table backwards and tries to detect and decode mbufs. 489 Use 'mbuf_walk_slabs decode' to decode the mbuf using scapy. 490 """ 491 decode_pkt = False 492 if len(cmd_args) > 0 and cmd_args[0] == 'decode': 493 decode_pkt = True 494 495 if int(kern.globals.mb_uses_mcache) == 0: 496 for mbuf in kmemory.Zone("mbuf").iter_allocated(gettype("mbuf")): 497 MbufDecode(value(mbuf.AddressOf()), decode_pkt) 498 return 499 500 slabstbl = kern.globals.slabstbl 501 nslabspmb = int(((1 << MBSHIFT) >> unsigned(kern.globals.page_shift))) 502 mbutl = cast(kern.globals.mbutl, 'unsigned char *') 503 x = unsigned(kern.globals.maxslabgrp) 504 while x >= 0: 505 slg = slabstbl[x] 506 if (slg == 0): 507 x -= 1 508 continue 509 j = 0 510 while j < nslabspmb: 511 sl = addressof(slg.slg_slab[j]) 512 obj = sl.sl_base 513 # Ignore slabs with a single chunk 514 # since that's unlikely to contain an mbuf 515 # (more likely a cluster). 516 if sl.sl_chunks > 1: 517 z = 0 518 c = sl.sl_len // sl.sl_chunks 519 520 while z < sl.sl_chunks: 521 obj = kern.GetValueFromAddress(sl.sl_base + c * z) 522 mbuf = cast(obj, 'struct mbuf *') 523 MbufDecode(mbuf, decode_pkt) 524 z += 1 525 j += 1 526 x -= 1 527 528# EndMacro: mbuf_walk_slabs 529 530def GetMbufMcaPtr(m, cl): 531 pgshift = int(kern.globals.page_shift) 532 ix = int((m - Cast(kern.globals.mbutl, 'char *')) >> pgshift) 533 page_addr = (Cast(kern.globals.mbutl, 'char *') + (ix << pgshift)) 534 535 536 if (int(cl) == 0): 537 midx = int((m - page_addr) >> 8) 538 mca = kern.globals.mclaudit[ix].cl_audit[midx] 539 elif (int(cl) == 1): 540 midx = int((m - page_addr) >> 11) 541 mca = kern.globals.mclaudit[ix].cl_audit[midx] 542 elif (int(cl) == 2): 543 midx = int((m - page_addr) >> 12) 544 mca = kern.globals.mclaudit[ix].cl_audit[midx] 545 else: 546 mca = kern.globals.mclaudit[ix].cl_audit[0] 547 return Cast(mca, 'mcache_audit_t *') 548 549def GetMbufSlab(m): 550 pgshift = int(kern.globals.page_shift) 551 gix = int((Cast(m, 'char *') - Cast(kern.globals.mbutl, 'char *')) >> MBSHIFT) 552 slabstbl = kern.globals.slabstbl 553 ix = int((Cast(m, 'char *') - Cast(slabstbl[gix].slg_slab[0].sl_base, 'char *')) >> pgshift) 554 return addressof(slabstbl[gix].slg_slab[ix]) 555 556def GetMbufBuf2Mca(m): 557 sl = GetMbufSlab(m) 558 mca = GetMbufMcaPtr(m, sl.sl_class) 559 return str(mca) 560 561def GetMbufWalkAllSlabs(show_a, show_f, show_tr): 562 out_string = "" 563 564 kern.globals.slabstbl[0] 565 566 x = 0 567 total = 0 568 total_a = 0 569 total_f = 0 570 571 if (show_a and not(show_f)): 572 out_string += "Searching only for active... \n" 573 if (not(show_a) and show_f): 574 out_string += "Searching only for inactive... \n" 575 if (show_a and show_f): 576 out_string += "Displaying all... \n" 577 578 if (kern.ptrsize == 8): 579 show_mca_string_format = "{0:>4s} {1:>4s} {2:>16s} {3:>16s} {4:>16} {5:>12s} {6:12s}" 580 out_string += show_mca_string_format.format("slot", "idx", "slab address", "mca address", "obj address", "type", "allocation state\n") 581 else: 582 show_mca_string_format = "{0:4s} {1:4s} {2:8s} {3:8s} {4:8} {5:12s} {6:12s}" 583 out_string += show_mca_string_format.format("slot", "idx", "slab address", "mca address", "obj address", "type", "allocation state\n") 584 585 nslabspmb = unsigned((1 << MBSHIFT) >> unsigned(kern.globals.page_shift)) 586 while (x < unsigned(kern.globals.slabgrp)): 587 slg = kern.globals.slabstbl[x] 588 y = 0 589 while (y < nslabspmb): 590 sl = addressof(slg.slg_slab[y]) 591 base = sl.sl_base 592 if (base == 0): 593 break 594 595 mca = GetMbufMcaPtr(base, sl.sl_class) 596 first = 1 597 598 while ((Cast(mca, 'int') != 0) and (unsigned(mca.mca_addr) != 0)): 599 printmca = 0 600 if (mca.mca_uflags & (MB_INUSE | MB_COMP_INUSE)): 601 total_a = total_a + 1 602 printmca = show_a 603 if (show_tr > 2) and (mca.mca_uflags & MB_SCVALID) == 0: 604 printmca = 0 605 else: 606 total_f = total_f + 1 607 printmca = show_f 608 609 if (printmca != 0): 610 if (first == 1): 611 if (kern.ptrsize == 8): 612 mca_string_format = "{0:4d} {1:4d} 0x{2:16x} " 613 out_string += mca_string_format.format(x, y, sl) 614 else: 615 mca_string_format = "{0:4d} {1:4d} 0x{02:8x} " 616 out_string += mca_string_format.format(x, y, sl) 617 else: 618 if (kern.ptrsize == 8): 619 out_string += " " 620 else: 621 out_string += " " 622 623 if (kern.ptrsize == 8): 624 mca_string_format = "0x{0:16x} 0x{1:16x}" 625 out_string += mca_string_format.format(mca, mca.mca_addr) 626 else: 627 mca_string_format = "0x{0:8x} 0x{1:8x}" 628 out_string += mca_string_format.format(mca, mca.mca_addr) 629 630 out_string += GetMbufMcaCtype(mca, 0) 631 632 if (mca.mca_uflags & (MB_INUSE | MB_COMP_INUSE)): 633 out_string += "active " 634 else: 635 out_string += " freed " 636 if (show_tr > 1) and (mca.mca_uflags & MB_SCVALID): 637 m = Cast(mca.mca_addr, 'struct mbuf *') 638 mbuf_string = GetMbufFlags(m) 639 mbuf_string += " " + GetMbufPktCrumbs(m) 640 if (mbuf_string != ""): 641 if (kern.ptrsize == 8): 642 out_string += "\n " + mbuf_string 643 else: 644 out_string += "\n " + mbuf_string 645 if (first == 1): 646 first = 0 647 648 out_string += "\n" 649 total = total + 1 650 651 if (show_tr != 0): 652 if (mca.mca_next_trn == 0): 653 trn = 1 654 else: 655 trn = 0 656 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" 657 cnt = 0 658 while (cnt < mca.mca_trns[int(trn)].mca_depth): 659 kgm_pc = mca.mca_trns[int(trn)].mca_stack[int(cnt)] 660 out_string += str(int(cnt) + 1) + " " 661 out_string += GetPc(kgm_pc) 662 cnt += 1 663 664 print(out_string) 665 out_string = "" 666 mca = mca.mca_next 667 668 y += 1 669 670 x += 1 671 672 if (total and show_a and show_f): 673 out_string += "total objects = " + str(int(total)) + "\n" 674 out_string += "active/unfreed objects = " + str(int(total_a)) + "\n" 675 out_string += "freed/in_cache objects = " + str(int(total_f)) + "\n" 676 677 return out_string 678 679def GetMbufFlagsAsString(mbuf_flags): 680 flags = (unsigned)(mbuf_flags & 0xff) 681 out_string = "" 682 i = 0 683 num = 1 684 while num <= flags: 685 if flags & num: 686 out_string += mbuf_flags_strings[i] + "," 687 i += 1 688 num = num << 1 689 return out_string.rstrip(",") 690 691def GetMbufFlags(m): 692 out_string = "" 693 if (m != 0): 694 if kern.globals.mb_uses_mcache == 1: 695 mhflags = m.m_hdr.mh_flags 696 else: 697 mhflags = m.M_hdr_common.M_hdr.mh_flags 698 out_string += "m_flags: " + hex(mhflags) 699 if (mhflags != 0): 700 out_string += " " + GetMbufFlagsAsString(mhflags) 701 return out_string 702 703MBUF_TYPES = [None] * 32 704MBUF_TYPES[0] = "MT_FREE" 705MBUF_TYPES[1] = "MT_DATA" 706MBUF_TYPES[2] = "MT_HEADER" 707MBUF_TYPES[3] = "MT_SOCKET" 708MBUF_TYPES[4] = "MT_PCB" 709MBUF_TYPES[5] = "MT_RTABLE" 710MBUF_TYPES[6] = "MT_HTABLE" 711MBUF_TYPES[7] = "MT_ATABLE" 712MBUF_TYPES[8] = "MT_SONAME" 713# 9 not used 714MBUF_TYPES[10] = "MT_SOOPTS" 715MBUF_TYPES[11] = "MT_FTABLE" 716MBUF_TYPES[12] = "MT_RIGHTS" 717MBUF_TYPES[13] = "MT_IFADDR" 718MBUF_TYPES[14] = "MT_CONTROL" 719MBUF_TYPES[15] = "MT_OOBDATA" 720MBUF_TYPES[16] = "MT_TAG" 721 722def GetMbufType(m): 723 out_string = "" 724 if (m != 0): 725 if kern.globals.mb_uses_mcache == 1: 726 mhtype = m.m_hdr.mh_type 727 else: 728 mhtype = m.M_hdr_common.M_hdr.mh_type 729 out_string += "type: " + MBUF_TYPES[mhtype] 730 return out_string 731 732# Macro: mbuf_show_m_flags 733@lldb_command('mbuf_show_m_flags') 734def MbufShowFlags(cmd_args=None): 735 """ Return a formatted string description of the mbuf flags 736 """ 737 m = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') 738 print(GetMbufFlags(m)) 739 740def GetMbufPktCrumbsAsString(mbuf_crumbs): 741 flags = (unsigned)(mbuf_crumbs & 0xffff) 742 out_string = "" 743 i = 0 744 num = 1 745 while num <= flags: 746 if flags & num: 747 out_string += mbuf_pkt_crumb_strings[i] + "," 748 i += 1 749 num = num << 1 750 return out_string.rstrip(",") 751 752def GetMbufPktCrumbs(m): 753 out_string = "" 754 if (m != 0): 755 if kern.globals.mb_uses_mcache == 1: 756 mhflags = m.m_hdr.mh_flags 757 else: 758 mhflags = m.M_hdr_common.M_hdr.mh_flags 759 if (mhflags & M_PKTHDR) != 0: 760 if kern.globals.mb_uses_mcache == 1: 761 pktcrumbs = m.m_hdr.pkt_crumbs 762 else: 763 pktcrumbs = m.M_hdr_common.M_pkthdr.pkt_crumbs 764 out_string += "pkt_crumbs: 0x{0:x}".format(pktcrumbs) 765 if (pktcrumbs != 0): 766 out_string += " " + GetMbufPktCrumbsAsString(pktcrumbs) 767 return out_string 768 769# Macro: mbuf_showpktcrumbs 770@lldb_command('mbuf_showpktcrumbs') 771def MbufShowPktCrumbs(cmd_args=None): 772 """ Print the packet crumbs of an mbuf object mca 773 """ 774 m = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') 775 print(GetMbufPktCrumbs(m)) 776 777def GetMbufMcaCtype(mca, vopt): 778 cp = mca.mca_cache 779 mca_class = unsigned(cp.mc_private) 780 csize = unsigned(kern.globals.mbuf_table[mca_class].mtbl_stats.mbcl_size) 781 done = 0 782 out_string = " " 783 if (csize == MSIZE): 784 if (vopt): 785 out_string += "M (mbuf) " 786 else: 787 out_string += "M " 788 return out_string 789 if (csize == MCLBYTES): 790 if (vopt): 791 out_string += "CL (2K cluster) " 792 else: 793 out_string += "CL " 794 return out_string 795 if (csize == MBIGCLBYTES): 796 if (vopt): 797 out_string += "BCL (4K cluster) " 798 else: 799 out_string += "BCL " 800 return out_string 801 if (csize == M16KCLBYTES): 802 if (vopt): 803 out_string += "JCL (16K cluster) " 804 else: 805 out_string += "JCL " 806 return out_string 807 808 if (csize == (MSIZE + MCLBYTES)): 809 if (mca.mca_uflags & MB_SCVALID): 810 if (mca.mca_uptr): 811 out_string += "M+CL " 812 if vopt: 813 out_string += "(paired mbuf, 2K cluster) " 814 else: 815 out_string += "M-CL " 816 if vopt: 817 out_string += "(unpaired mbuf, 2K cluster) " 818 else: 819 if (mca.mca_uptr): 820 out_string += "CL+M " 821 if vopt: 822 out_string += "(paired 2K cluster, mbuf) " 823 else: 824 out_string += "CL-M " 825 if vopt: 826 out_string += "(unpaired 2K cluster, mbuf) " 827 return out_string 828 829 if (csize == (MSIZE + MBIGCLBYTES)): 830 if (mca.mca_uflags & MB_SCVALID): 831 if (mca.mca_uptr): 832 out_string += "M+BCL " 833 if vopt: 834 out_string += "(paired mbuf, 4K cluster) " 835 else: 836 out_string += "M-BCL " 837 if vopt: 838 out_string += "(unpaired mbuf, 4K cluster) " 839 else: 840 if (mca.mca_uptr): 841 out_string += "BCL+M " 842 if vopt: 843 out_string += "(paired 4K cluster, mbuf) " 844 else: 845 out_string += "BCL-m " 846 if vopt: 847 out_string += "(unpaired 4K cluster, mbuf) " 848 return out_string 849 850 if (csize == (MSIZE + M16KCLBYTES)): 851 if (mca.mca_uflags & MB_SCVALID): 852 if (mca.mca_uptr): 853 out_string += "M+BCL " 854 if vopt: 855 out_string += "(paired mbuf, 4K cluster) " 856 else: 857 out_string += "M-BCL " 858 if vopt: 859 out_string += "(unpaired mbuf, 4K cluster) " 860 else: 861 if (mca.mca_uptr): 862 out_string += "BCL+M " 863 if vopt: 864 out_string += "(paired 4K cluster, mbuf) " 865 else: 866 out_string += "BCL-m " 867 if vopt: 868 out_string += "(unpaired 4K cluster, mbuf) " 869 return out_string 870 871 out_string += "unknown: " + cp.mc_name 872 return out_string 873 874 875def GetPointerAsString(kgm_pc): 876 if (kern.ptrsize == 8): 877 pointer_format_string = "0x{0:<16x} " 878 else: 879 pointer_format_string = "0x{0:<8x} " 880 return pointer_format_string.format(kgm_pc) 881 882def GetPc(kgm_pc): 883 out_string = GetSourceInformationForAddress(unsigned(kgm_pc)) + "\n" 884 return out_string 885 886 887def GetMbufWalkZone(show_a, show_f, show_tr): 888 out_string = "" 889 total = 0 890 total_a = 0 891 total_f = 0 892 if (show_a and not(show_f)): 893 out_string += "Searching only for active... \n" 894 if (not(show_a) and show_f): 895 out_string += "Searching only for inactive... \n" 896 if (show_a and show_f): 897 out_string += "Displaying all... \n" 898 f = "{0:>18s} {1:s}\n" 899 out_string += f.format("address", "type flags and crumbs") 900 print(out_string) 901 if show_a: 902 for mbuf_sbv in kmemory.Zone("mbuf").iter_allocated(gettype("mbuf")): 903 mbuf = value(mbuf_sbv.AddressOf()) 904 total_a += 1 905 total += 1 906 mbuf_string = GetMbufFlags(mbuf) 907 mbuf_string += " " + GetMbufType(mbuf) 908 mbuf_string += " " + GetMbufPktCrumbs(mbuf) 909 if mbuf_string != "": 910 out_string = f.format(hex(mbuf), mbuf_string) 911 print(out_string) 912 if show_tr: 913 print(lldb_run_command('kasan whatis {addr}'.format(addr=hex(mbuf)))) 914 if show_f: 915 for mbuf_sbv in kmemory.Zone("mbuf").iter_free(gettype("mbuf")): 916 mbuf = value(mbuf_sbv.AddressOf()) 917 total_f += 1 918 total += 1 919 mbuf_string = GetMbufFlags(mbuf) 920 mbuf_string += " " + GetMbufType(mbuf) 921 mbuf_string += " " + GetMbufPktCrumbs(mbuf) 922 if mbuf_string != "": 923 out_string = f.format(hex(mbuf), mbuf_string) 924 print(out_string) 925 if show_tr: 926 print(lldb_run_command('kasan whatis {addr}'.format(addr=hex(mbuf)))) 927 928 if total and show_a and show_f: 929 out_string += "total objects = " + str(int(total)) + "\n" 930 out_string += "active/unfreed objects = " + str(int(total_a)) + "\n" 931 out_string += "freed/in_cache objects = " + str(int(total_f)) + "\n" 932 print(out_string) 933 934 935# Macro: mbuf_showactive 936@lldb_command('mbuf_showactive') 937def MbufShowActive(cmd_args=None): 938 """ Print all active/in-use mbuf objects 939 Pass 1 to show the most recent transaction stack trace 940 Pass 2 to also display the mbuf flags and packet crumbs 941 Pass 3 to limit display to mbuf and skip clusters 942 """ 943 if int(kern.globals.mb_uses_mcache) == 0: 944 if cmd_args: 945 GetMbufWalkZone(1, 0, ArgumentStringToInt(cmd_args[0])) 946 else: 947 GetMbufWalkZone(1, 0, 0) 948 else: 949 if cmd_args: 950 print(GetMbufWalkAllSlabs(1, 0, ArgumentStringToInt(cmd_args[0]))) 951 else: 952 print(GetMbufWalkAllSlabs(1, 0, 0)) 953# EndMacro: mbuf_showactive 954 955 956# Macro: mbuf_showinactive 957@lldb_command('mbuf_showinactive') 958def MbufShowInactive(cmd_args=None): 959 """ Print all freed/in-cache mbuf objects 960 """ 961 if int(kern.globals.mb_uses_mcache) == 0: 962 GetMbufWalkZone(0, 1, 0) 963 else: 964 print(GetMbufWalkAllSlabs(0, 1, 0)) 965# EndMacro: mbuf_showinactive 966 967# Macro: mbuf_show_type_summary 968@lldb_command('mbuf_show_type_summary') 969def MbufShowTypeSummary(cmd_args=None): 970 """ 971 Print types of all allocated mbufs. 972 Only supported on Apple Silicon. 973 """ 974 types = [0] * 32 975 for mbuf_sbv in kmemory.Zone("mbuf").iter_allocated(gettype("mbuf")): 976 mbuf = value(mbuf_sbv.AddressOf()) 977 mhtype = mbuf.M_hdr_common.M_hdr.mh_type 978 types[mhtype] += 1 979 for mbuf_sbv in kmemory.Zone("mbuf").iter_free(gettype("mbuf")): 980 mbuf = value(mbuf_sbv.AddressOf()) 981 mhtype = mbuf.M_hdr_common.M_hdr.mh_type 982 types[mhtype] += 1 983 984 print("mbuf types allocated and in the caches:") 985 for t in range(len(MBUF_TYPES)): 986 if types[t] != 0: 987 print(MBUF_TYPES[t], types[t]) 988 989# EndMacro: mbuf_show_type_summary 990 991 992# Macro: mbuf_showmca 993@lldb_command('mbuf_showmca') 994def MbufShowMca(cmd_args=None): 995 """ Print the contents of an mbuf mcache audit structure 996 """ 997 if int(kern.globals.mb_uses_mcache) == 0: 998 print("mcache is disabled, use kasan whatis or zstack_findelem") 999 return 1000 out_string = "" 1001 pgshift = unsigned(kern.globals.page_shift) 1002 if cmd_args: 1003 mca = kern.GetValueFromAddress(cmd_args[0], 'mcache_audit_t *') 1004 cp = mca.mca_cache 1005 out_string += "object type:\t" 1006 out_string += GetMbufMcaCtype(mca, 1) 1007 out_string += "\nControlling mcache :\t" + hex(mca.mca_cache) + " (" + str(cp.mc_name) + ")\n" 1008 if (mca.mca_uflags & MB_INUSE): 1009 out_string += " inuse" 1010 if (mca.mca_uflags & MB_COMP_INUSE): 1011 out_string += " comp_inuse" 1012 if (mca.mca_uflags & MB_SCVALID): 1013 out_string += " scvalid" 1014 out_string += "\n" 1015 if (mca.mca_uflags & MB_SCVALID): 1016 mbutl = Cast(kern.globals.mbutl, 'unsigned char *') 1017 ix = (mca.mca_addr - mbutl) >> pgshift 1018 clbase = mbutl + (ix << pgshift) 1019 mclidx = (mca.mca_addr - clbase) >> 8 1020 out_string += "mbuf obj :\t\t" + hex(mca.mca_addr) + "\n" 1021 out_string += "mbuf index :\t\t" + str(mclidx + 1) + " (out of 16) in cluster base " + hex(clbase) + "\n" 1022 if (int(mca.mca_uptr) != 0): 1023 peer_mca = cast(mca.mca_uptr, 'mcache_audit_t *') 1024 out_string += "paired cluster obj :\t" + hex(peer_mca.mca_addr) + " (mca " + hex(peer_mca) + ")\n" 1025 out_string += "saved contents :\t" + hex(mca.mca_contents) + " (" + str(int(mca.mca_contents_size)) + " bytes)\n" 1026 else: 1027 out_string += "cluster obj :\t\t" + hex(mca.mca_addr) + "\n" 1028 if (mca.mca_uptr != 0): 1029 peer_mca = cast(mca.mca_uptr, 'mcache_audit_t *') 1030 out_string += "paired mbuf obj :\t" + hex(peer_mca.mca_addr) + " (mca " + hex(peer_mca) + ")\n" 1031 1032 for idx in range(unsigned(kern.globals.mca_trn_max), 0, -1): 1033 trn = (mca.mca_next_trn + idx - 1) % unsigned(kern.globals.mca_trn_max) 1034 out_string += "transaction {:d} (tstamp {:d}, thread 0x{:x}):\n".format(trn, mca.mca_trns[trn].mca_tstamp, mca.mca_trns[trn].mca_thread) 1035 cnt = 0 1036 while (cnt < mca.mca_trns[trn].mca_depth): 1037 kgm_pc = mca.mca_trns[trn].mca_stack[cnt] 1038 out_string += " " + str(cnt + 1) + ". " 1039 out_string += GetPc(kgm_pc) 1040 cnt += 1 1041 1042 msc = cast(mca.mca_contents, 'mcl_saved_contents_t *') 1043 msa = addressof(msc.sc_scratch) 1044 if (mca.mca_uflags & MB_SCVALID): 1045 if (msa.msa_depth > 0): 1046 out_string += "Recent scratch transaction (tstamp {:d}, thread 0x{:x}):\n".format(msa.msa_tstamp, msa.msa_thread) 1047 cnt = 0 1048 while (cnt < msa.msa_depth): 1049 kgm_pc = msa.msa_stack[cnt] 1050 out_string += " " + str(cnt + 1) + ". " 1051 out_string += GetPc(kgm_pc) 1052 cnt += 1 1053 1054 if (msa.msa_pdepth > 0): 1055 out_string += "previous scratch transaction (tstamp {:d}, thread 0x{:x}):\n".format(msa.msa_ptstamp, msa.msa_pthread) 1056 if (msa): 1057 cnt = 0 1058 while (cnt < msa.msa_pdepth): 1059 kgm_pc = msa.msa_pstack[cnt] 1060 out_string += " " + str(cnt + 1) + ". " 1061 out_string += GetPc(kgm_pc) 1062 cnt += 1 1063 else: 1064 out_string += "Missing argument 0 in user function." 1065 1066 print(out_string) 1067# EndMacro: mbuf_showmca 1068 1069 1070# Macro: mbuf_showall 1071@lldb_command('mbuf_showall') 1072def MbufShowAll(cmd_args=None): 1073 """ Print all mbuf objects 1074 """ 1075 if int(kern.globals.mb_uses_mcache) == 0: 1076 GetMbufWalkZone(1, 1, 1) 1077 else: 1078 print(GetMbufWalkAllSlabs(1, 1, 1)) 1079# EndMacro: mbuf_showall 1080 1081# Macro: mbuf_countchain 1082@lldb_command('mbuf_countchain') 1083def MbufCountChain(cmd_args=None): 1084 """ Count the length of an mbuf chain 1085 """ 1086 if not cmd_args: 1087 raise ArgumentError("Missing argument 0 in user function.") 1088 1089 mp = kern.GetValueFromAddress(cmd_args[0], 'mbuf *') 1090 1091 pkt = 0 1092 nxt = 0 1093 1094 while (mp): 1095 pkt = pkt + 1 1096 if kern.globals.mb_uses_mcache == 1: 1097 mn = mp.m_hdr.mh_next 1098 else: 1099 mn = mp.M_hdr_common.M_hdr.mh_next 1100 while (mn): 1101 nxt = nxt + 1 1102 if kern.globals.mb_uses_mcache == 1: 1103 mn = mn.m_hdr.mh_next 1104 else: 1105 mn = mn.M_hdr_common.M_hdr.mh_next 1106 print1("mp 0x{:x} mn 0x{:x}".format(mp, mn)) 1107 1108 if kern.globals.mb_uses_mcache == 1: 1109 mp = mp.m_hdr.mh_nextpkt 1110 else: 1111 mp = mp.M_hdr_common.M_hdr.mh_nextpkt 1112 1113 if (((pkt + nxt) % 50) == 0): 1114 print(" ..." + str(pkt_nxt)) 1115 1116 print("Total: " + str(pkt + nxt) + " (via m_next: " + str(nxt) + ")") 1117# EndMacro: mbuf_countchain 1118 1119# Macro: mbuf_topleak 1120@lldb_command('mbuf_topleak') 1121def MbufTopLeak(cmd_args=None): 1122 """ Print the top suspected mbuf leakers 1123 """ 1124 if int(kern.globals.mb_uses_mcache) == 0: 1125 print("mcache is disabled, use zleak") 1126 return 1127 topcnt = 0 1128 if (int(len(cmd_args)) > 0 and int(cmd_args[0]) < 5): 1129 maxcnt = cmd_args[0] 1130 else: 1131 maxcnt = 5 1132 while (topcnt < maxcnt): 1133 print(GetMbufTraceLeak(kern.globals.mleak_top_trace[topcnt])) 1134 topcnt += 1 1135 1136# EndMacro: mbuf_topleak 1137 1138def GetMbufTraceLeak(trace): 1139 out_string = "" 1140 if (trace != 0 and trace.allocs != 0): 1141 out_string += hex(trace) + ":" + str(trace.allocs) + " outstanding allocs\n" 1142 out_string += "Backtrace saved " + str(trace.depth) + " deep\n" 1143 if (trace.depth != 0): 1144 cnt = 0 1145 while (cnt < trace.depth): 1146 out_string += str(cnt + 1) + ": " 1147 out_string += GetPc(trace.addr[cnt]) 1148 out_string += "\n" 1149 cnt += 1 1150 return out_string 1151 1152@lldb_command('mbuf_largefailures') 1153def MbufLargeFailures(cmd_args=None): 1154 """ Print the largest allocation failures 1155 """ 1156 if int(kern.globals.mb_uses_mcache) == 0: 1157 print("mcache is disabled, this macro is not available. use zleak to detect leaks") 1158 return 1159 topcnt = 0 1160 if (int(len(cmd_args)) > 0 and int(cmd_args[0]) < 5): 1161 maxcnt = cmd_args[0] 1162 else: 1163 maxcnt = 5 1164 while (topcnt < maxcnt): 1165 trace = kern.globals.mtracelarge_table[topcnt] 1166 if (trace.size == 0): 1167 topcnt += 1 1168 continue 1169 print(str(trace.size)) 1170 if (trace.depth != 0): 1171 cnt = 0 1172 while (cnt < trace.depth): 1173 print(str(cnt + 1) + ": " + GetPc(trace.addr[cnt])) 1174 cnt += 1 1175 topcnt += 1 1176 1177 1178# Macro: mbuf_traceleak 1179@lldb_command('mbuf_traceleak') 1180def MbufTraceLeak(cmd_args=None): 1181 """ Print the leak information for a given leak address 1182 Given an mbuf leak trace (mtrace) structure address, print out the 1183 stored information with that trace 1184 syntax: (lldb) mbuf_traceleak <addr> 1185 """ 1186 if not cmd_args: 1187 raise ArgumentError("Missing argument 0 in user function.") 1188 if int(kern.globals.mb_uses_mcache) == 0: 1189 print("mcache is disabled, use kasan whatis") 1190 return 1191 1192 trace = kern.GetValueFromAddress(cmd_args[0], 'mtrace *') 1193 print(GetMbufTraceLeak(trace)) 1194# EndMacro: mbuf_traceleak 1195 1196 1197# Macro: mcache_walkobj 1198@lldb_command('mcache_walkobj') 1199def McacheWalkObject(cmd_args=None): 1200 """ Given a mcache object address, walk its obj_next pointer 1201 """ 1202 if not cmd_args: 1203 raise ArgumentError("Missing argument 0 in user function.") 1204 if int(kern.globals.mb_uses_mcache) == 0: 1205 print("mcache is disabled, use kasan whatis") 1206 return 1207 1208 out_string = "" 1209 p = kern.GetValueFromAddress(cmd_args[0], 'mcache_obj_t *') 1210 cnt = 1 1211 total = 0 1212 while (p): 1213 mcache_object_format = "{0:>4d}: 0x{1:>16x}" 1214 out_string += mcache_object_format.format(cnt, p) + "\n" 1215 p = p.obj_next 1216 cnt += 1 1217 print(out_string) 1218# EndMacro: mcache_walkobj 1219 1220# Macro: mcache_stat 1221@lldb_command('mcache_stat') 1222def McacheStat(cmd_args=None): 1223 """ Print all mcaches in the system. 1224 """ 1225 if int(kern.globals.mb_uses_mcache) == 0: 1226 print("mcache is disabled, use kasan whatis") 1227 return 1228 1229 head = kern.globals.mcache_head 1230 out_string = "" 1231 mc = cast(head.lh_first, 'mcache *') 1232 if (kern.ptrsize == 8): 1233 mcache_stat_format_string = "{0:<24s} {1:>8s} {2:>20s} {3:>5s} {4:>5s} {5:>20s} {6:>30s} {7:>18s}" 1234 else: 1235 mcache_stat_format_string = "{0:<24s} {1:>8s} {2:>12s} {3:>5s} {4:>5s} {5:>12s} {6:>30s} {7:>18s}" 1236 1237 if (kern.ptrsize == 8): 1238 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}" 1239 else: 1240 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}" 1241 1242 out_string += mcache_stat_format_string.format("cache name", "cache state", "cache addr", "buf size", "buf align", "backing zone", "wait nowait failed", "bufs incache") 1243 out_string += "\n" 1244 1245 ncpu = int(kern.globals.ncpu) 1246 while mc != 0: 1247 bktsize = mc.mc_cpu[0].cc_bktsize 1248 cache_state = "" 1249 if (mc.mc_flags & MCF_NOCPUCACHE): 1250 cache_state = "disabled" 1251 else: 1252 if (bktsize == 0): 1253 cache_state = " offline" 1254 else: 1255 cache_state = " online" 1256 if (mc.mc_slab_zone != 0): 1257 backing_zone = mc.mc_slab_zone 1258 else: 1259 if (kern.ptrsize == 8): 1260 backing_zone = " custom" 1261 else: 1262 backing_zone = " custom" 1263 1264 total = 0 1265 total += mc.mc_full.bl_total * bktsize 1266 n = 0 1267 while(n < ncpu): 1268 ccp = mc.mc_cpu[n] 1269 if (ccp.cc_objs > 0): 1270 total += ccp.cc_objs 1271 if (ccp.cc_pobjs > 0): 1272 total += ccp.cc_pobjs 1273 n += 1 1274 1275 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) 1276 out_string += "\n" 1277 mc = cast(mc.mc_list.le_next, 'mcache *') 1278 print(out_string) 1279# EndMacro: mcache_stat 1280 1281# Macro: mcache_showcache 1282@lldb_command('mcache_showcache') 1283def McacheShowCache(cmd_args=None): 1284 """Display the number of objects in cache. 1285 """ 1286 if int(kern.globals.mb_uses_mcache) == 0: 1287 print("mcache is disabled, use kasan whatis") 1288 return 1289 out_string = "" 1290 cp = kern.GetValueFromAddress(cmd_args[0], 'mcache_t *') 1291 bktsize = cp.mc_cpu[0].cc_bktsize 1292 cnt = 0 1293 total = 0 1294 mcache_cache_format = "{0:<4d} {1:>8d} {2:>8d} {3:>8d}" 1295 out_string += "Showing cache " + str(cp.mc_name) + " :\n\n" 1296 out_string += " CPU cc_objs cc_pobjs total\n" 1297 out_string += "---- ------- -------- --------\n" 1298 ncpu = int(kern.globals.ncpu) 1299 while (cnt < ncpu): 1300 ccp = cp.mc_cpu[cnt] 1301 objs = ccp.cc_objs 1302 if (objs <= 0): 1303 objs = 0 1304 pobjs = ccp.cc_pobjs 1305 if (pobjs <= 0): 1306 pobjs = 0 1307 tot_cpu = objs + pobjs 1308 total += tot_cpu 1309 out_string += mcache_cache_format.format(cnt, objs, pobjs, tot_cpu) 1310 out_string += "\n" 1311 cnt += 1 1312 1313 out_string += " ========\n" 1314 out_string += " " + str(total) + "\n\n" 1315 total += cp.mc_full.bl_total * bktsize 1316 1317 out_string += "Total # of full buckets (" + str(int(bktsize)) + " objs/bkt):\t" + str(int(cp.mc_full.bl_total)) + "\n" 1318 out_string += "Total # of objects cached:\t\t" + str(total) + "\n" 1319 print(out_string) 1320# EndMacro: mcache_showcache 1321 1322# Macro: mbuf_wdlog 1323@lldb_command('mbuf_wdlog') 1324def McacheShowWatchdogLog(cmd_args=None): 1325 """Display the watchdog log 1326 """ 1327 lldb_run_command('settings set max-string-summary-length 4096') 1328 print('%s' % lldb_run_command('p/s mbwdog_logging').replace("\\n","\n")) 1329# EndMacro: mbuf_wdlog 1330