from .commands import LunadbgCommand from .structs.pagetable import PageTable, PageTableEntry from .pp import MyPrettyPrinter from gdb import parse_and_eval, lookup_type class PteInterpreter(LunadbgCommand): def __init__(self) -> None: super().__init__("pte") self._parser.description = "Interpret the PTE based on give raw value or ptep" self._parser.add_argument("val") self._parser.add_argument("--va", action='store_true', default=False, help="treat the given as virtual address") self._parser.add_argument("--ptep", action='store_true', default=False, help="treat the given as ptep") self._parser.add_argument('-l', "--at-level", type=int, default=-1, help="translation level that the given virtual address located") self._parser.add_argument('-m', "--mnt", default=-1, help="vms mount point that the given virtual address located") @staticmethod def print_pte(pp, pte_val, level): pte = PageTableEntry.from_pteval(pte_val, level) pp.print(pte) @staticmethod def print_ptep(pp, ptep, level): pte = PageTableEntry(ptep, level) pp.print(pte) def on_execute(self, parsed, gdb_args, from_tty): pp = MyPrettyPrinter() val = int(parse_and_eval(parsed.val)) lvl = parsed.at_level if not parsed.va: PteInterpreter.print_pte(pp, val, lvl) return if not parsed.ptep: ptep = PageTable.mkptep_at(parsed.mnt, val, lvl) PteInterpreter.print_ptep(pp, ptep, lvl) return PteInterpreter.print_ptep(pp, val, lvl) class PtepInterpreter(LunadbgCommand): def __init__(self) -> None: super().__init__("ptep") self._parser.description = "Manipulate the pte pointer" self._parser.add_argument("ptep") self._parser.add_argument("--pfn", action='store_true', default=False, help="get the pfn (relative to mount point) implied by this ptep") self._parser.add_argument("--vfn", action='store_true', default=False, help="get the vfn implied by this ptep") self._parser.add_argument("--level", action='store_true', default=False, help="estimate the translation level implied by this ptep") self._parser.add_argument("--to-level", type=int, default=None, help="convert given ptep to specified level before any other processing") self._parser.add_argument("--sn", action='store_true', default=False, help="shift the ptep to next translation level") self._parser.add_argument("--sp", action='store_true', default=False, help="shift the ptep to previous translation level") def on_execute(self, parsed, gdb_args, from_tty): pp = MyPrettyPrinter() ptep = int(parse_and_eval(parsed.ptep)) if parsed.to_level is not None: ptep = PageTable.get_lntep(ptep, parsed.to_level) pp.printf("ptep: 0x%016x", ptep) if parsed.pfn: ptep = PageTable.get_pfn(ptep) pp.set_prefix("pfn: ") elif parsed.vfn: ptep = PageTable.get_vfn(ptep) pp.set_prefix("vfn: ") elif parsed.level: l, m = PageTable.ptep_infer_level(ptep) pp.printf("Level %d ptep (mnt=0x%016x, vfn=%d)", l, m, PageTable.get_vfn(ptep)) return elif parsed.sn: ptep = PageTable.shift_ptep_nextlevel(ptep) elif parsed.sp: ptep = PageTable.shift_ptep_prevlevel(ptep) pp.printf("0x%016x", ptep)