1 from .commands import LunadbgCommand
2 from .pp import MyPrettyPrinter
3 from .profiling.pmstat import PhysicalMemProfile
4 from .structs.pagetable import PageTable
5 from .arch.x86 import PageTableHelper
7 class MMStats(LunadbgCommand):
8 def __init__(self) -> None:
10 subparsers = self._parser.add_subparsers(dest="cmd")
12 stats = subparsers.add_parser("stats")
13 stats.add_argument("state_type")
14 stats.add_argument("-g", "--granule", type=int, default=512)
15 stats.add_argument("--cols", type=int, default=32)
17 lookup = subparsers.add_parser("lookup")
18 lookup.add_argument("mem_type")
19 lookup.add_argument("address")
20 lookup.add_argument("-l", "--level", type=int, default=-1)
21 lookup.add_argument("-n", type=int, default=0)
22 lookup.add_argument("-t", "--to", dest="to_addr", default='0')
24 self.__ptw = PageTable()
26 def print_pmem_stats(self, pp: MyPrettyPrinter, optn):
27 pmem = PhysicalMemProfile()
28 pmem.rescan_pmem(optn.granule)
30 pp.printf("Total: %dKiB (%d@4K)",
31 pmem.max_mem_sz / 1024, pmem.max_mem_pg)
33 pp.printf("Used: %dKiB (%d@4K) ~%.2f%%",
34 pmem.consumed_pg * 4096 / 1024,
35 pmem.consumed_pg, pmem.utilisation * 100)
37 pp.printf("Fragmentations: %d ~%.2f%%", pmem.discontig, pmem.fragmentation * 100)
40 pp.print("Distribution")
41 pp.print("( . = empty, * = full, [0-9]0% full )")
42 pp2 = pp.next_level(2)
44 for i in range(0, len(pmem.mem_distr)):
45 ratio = pmem.mem_distr[i] / pmem.page_per_granule
54 if (i + 1) % optn.cols == 0:
55 pp2.print(''.join(row))
57 if (i + 1) % optn.cols != 0:
58 pp2.print(''.join(row))
60 pp.printf("(granule: %d, density: %d@4K)", optn.granule, pmem.page_per_granule)
62 def vm_lookup(self, pp, va, optn):
63 to_addr = int(optn.to_addr, 0)
64 vmt = PageTableHelper.vm_mnt()
65 if not optn.n and not to_addr:
66 pp.print(self.__ptw.get_pte(va, level=optn.level, mnt=vmt))
70 self.__ptw.print_ptes_between(pp, va, to_addr, optn.level, mnt=vmt)
72 self.__ptw.print_ptes(pp, va, optn.n, optn.level, mnt=vmt)
74 def __do_stats(self, pp, optn):
75 if optn.state_type == "pmem":
76 self.print_pmem_stats(pp, optn)
78 print("unknow stats type:", optn.state_type)
80 def __do_lookup(self, pp, address, optn):
81 if optn.mem_type == "vm":
82 self.vm_lookup(pp, int(address, base=0), optn)
84 print("unknow mem type:", optn.state_type)
86 def on_execute(self, optn, gdb_args, from_tty) -> None:
87 pp = MyPrettyPrinter()
89 if optn.cmd == 'stats':
90 self.__do_stats(pp, optn)
91 elif optn.cmd == 'lookup':
92 self.__do_lookup(pp, optn.address, optn)
94 print("unknown command:", optn.cmd)