From aa1b1d4a2543cc2965a85f70fe5eac077102bdf7 Mon Sep 17 00:00:00 2001 From: hugsy Date: Sat, 19 Aug 2023 18:06:35 -0700 Subject: [PATCH 01/11] added docstrings --- examples/fib.py | 35 ++- python/inc/bochscpu.hpp | 95 +++++-- python/src/bochscpu.cpp | 529 +++++++++++++++++++----------------- python/src/bochscpu_mem.cpp | 61 +++++ 4 files changed, 432 insertions(+), 288 deletions(-) diff --git a/examples/fib.py b/examples/fib.py index 019db5f..0089fe5 100644 --- a/examples/fib.py +++ b/examples/fib.py @@ -36,7 +36,14 @@ def mmap(sz: int = PAGE_SIZE, perm: str = "rw"): libc = ctypes.CDLL("libc.so.6") mmap = libc.mmap mmap.restype = ctypes.c_void_p - mmap.argtypes = [ctypes.c_void_p, ctypes.c_size_t, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_long] + mmap.argtypes = [ + ctypes.c_void_p, + ctypes.c_size_t, + ctypes.c_int, + ctypes.c_int, + ctypes.c_int, + ctypes.c_long, + ] flags = 0 match perm: case "ro": @@ -44,7 +51,7 @@ def mmap(sz: int = PAGE_SIZE, perm: str = "rw"): case "rw": flags = PROT_READ | PROT_WRITE case "rwx": - flags = PROT_READ | PROT_WRITE | PROT_EXECUTE + flags = PROT_READ | PROT_WRITE | PROT_EXEC case _: raise ValueError return mmap(-1, sz, flags, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) @@ -85,7 +92,7 @@ def VirtualAlloc(sz: int = PAGE_SIZE, perm: str = "rw"): def dump_page_table(addr: int, level: int = 0): level_str = ("PML", "PDPT", "PD", "PT") if level == 4: - data = bytes(bochscpu.bochscpu_mem_phy_read(addr, 8)) + data = bytes(bochscpu.memory.phy_read(addr, 8)) entry = struct.unpack(" {shellcode_gpa=:#x} -> {shellcode_hva=:#x}") - bochscpu.bochscpu_mem_page_insert(shellcode_gpa, shellcode_hva) + bochscpu.memory.page_insert(shellcode_gpa, shellcode_hva) stack_hva = VirtualAlloc() stack_gva = 0x0401_0000 stack_gpa = 0x1401_0000 dbg(f"inserting {stack_gva=:#x} -> {stack_gpa=:#x} -> {stack_hva=:#x}") - bochscpu.bochscpu_mem_page_insert(stack_gpa, stack_hva) + bochscpu.memory.page_insert(stack_gpa, stack_hva) pt = bochscpu.memory.PageMapLevel4Table() pt.Insert(stack_gva, stack_gpa, RW) @@ -210,21 +217,21 @@ def emulate(code: bytes): layout = pt.Commit(pml4) for hva, gpa in layout: - bochscpu.bochscpu_mem_page_insert(gpa, hva) - evaled_gpa = bochscpu.bochscpu_mem_phy_translate(gpa) + bochscpu.memory.page_insert(gpa, hva) + evaled_gpa = bochscpu.memory.phy_translate(gpa) assert evaled_gpa == hva, f"{evaled_gpa=:#x} == {hva=:#x}" - evaled_gpa = bochscpu.bochscpu_mem_virt_translate(pml4, shellcode_gva) + evaled_gpa = bochscpu.memory.virt_translate(pml4, shellcode_gva) assert evaled_gpa == shellcode_gpa, f"{evaled_gpa=:#x} != {shellcode_gpa=:#x}" - evaled_gpa = bochscpu.bochscpu_mem_virt_translate(pml4, stack_gva) + evaled_gpa = bochscpu.memory.virt_translate(pml4, stack_gva) assert evaled_gpa == stack_gpa, f"{evaled_gpa=:#x} != {stack_gpa=:#x}" # dump_page_table(pml4) dbg(f"copy code to {shellcode_gva=:#x}") - assert bochscpu.bochscpu_mem_virt_write(pml4, shellcode_gva, bytes(code)) + assert bochscpu.memory.virt_write(pml4, shellcode_gva, bytes(code)) dbg(f"copied to {shellcode_gva=:#x}, testing...") - data = bochscpu.bochscpu_mem_virt_read(pml4, shellcode_gva, len(code)) + data = bochscpu.memory.virt_read(pml4, shellcode_gva, len(code)) assert data assert bytes(data) == bytes(code), f"{bytes(data).hex()} != {bytes(code).hex()}" dbg("success") @@ -277,7 +284,9 @@ def emulate(code: bytes): t1 = time.time_ns() sess.run(hooks) t2 = time.time_ns() - dbg(f"vm stopped, execution: {stats.insn_nb} insns in {t2-t1}ns") + dbg( + f"vm stopped, execution: {stats.insn_nb} insns in {t2-t1}ns (~{int(stats.insn_nb // ((t2-t1)/1_000_000_000))}) insn/s" + ) dbg( f"mem accesses: read={stats.mem_access[0]} write={stats.mem_access[1]} execute={stats.mem_access[2]}" ) diff --git a/python/inc/bochscpu.hpp b/python/inc/bochscpu.hpp index d387006..2d4b1f7 100644 --- a/python/inc/bochscpu.hpp +++ b/python/inc/bochscpu.hpp @@ -56,36 +56,44 @@ namespace BochsCPU { -struct Session; +enum class InstructionType +{ + BX_INSTR_IS_JMP = BX_INSTR_IS_JMP, + BOCHSCPU_INSTR_IS_JMP_INDIRECT = BOCHSCPU_INSTR_IS_JMP_INDIRECT, + BOCHSCPU_INSTR_IS_CALL = BOCHSCPU_INSTR_IS_CALL, + BOCHSCPU_INSTR_IS_CALL_INDIRECT = BOCHSCPU_INSTR_IS_CALL_INDIRECT, + BOCHSCPU_INSTR_IS_RET = BOCHSCPU_INSTR_IS_RET, + BOCHSCPU_INSTR_IS_IRET = BOCHSCPU_INSTR_IS_IRET, + BOCHSCPU_INSTR_IS_INT = BOCHSCPU_INSTR_IS_INT, + BOCHSCPU_INSTR_IS_SYSCALL = BOCHSCPU_INSTR_IS_SYSCALL, + BOCHSCPU_INSTR_IS_SYSRET = BOCHSCPU_INSTR_IS_SYSRET, + BOCHSCPU_INSTR_IS_SYSENTER = BOCHSCPU_INSTR_IS_SYSENTER, + BOCHSCPU_INSTR_IS_SYSEXIT = BOCHSCPU_INSTR_IS_SYSEXIT, +}; -struct Hook + +enum class HookType { - void* ctx {nullptr}; - std::function before_execution; - std::function after_execution; - std::function reset; - std::function hlt; - std::function mwait; - std::function cnear_branch_taken; - std::function cnear_branch_not_taken; - std::function ucnear_branch; - std::function far_branch; - std::function vmexit; - std::function interrupt; - std::function hw_interrupt; - std::function clflush; - std::function tlb_cntrl; - std::function cache_cntrl; - std::function prefetch_hint; - std::function wrmsr; - std::function repeat_iteration; - std::function lin_access; - std::function phy_access; - std::function inp; - std::function inp2; - std::function outp; - std::function opcode; - std::function exception; + BOCHSCPU_HOOK_MEM_READ = BOCHSCPU_HOOK_MEM_READ, + BOCHSCPU_HOOK_MEM_WRITE = BOCHSCPU_HOOK_MEM_WRITE, + BOCHSCPU_HOOK_MEM_EXECUTE = BOCHSCPU_HOOK_MEM_EXECUTE, + BOCHSCPU_HOOK_MEM_RW = BOCHSCPU_HOOK_MEM_RW, + BOCHSCPU_HOOK_TLB_CR0 = BOCHSCPU_HOOK_TLB_CR0, + BOCHSCPU_HOOK_TLB_CR3 = BOCHSCPU_HOOK_TLB_CR3, + BOCHSCPU_HOOK_TLB_CR4 = BOCHSCPU_HOOK_TLB_CR4, + BOCHSCPU_HOOK_TLB_TASKSWITCH = BOCHSCPU_HOOK_TLB_TASKSWITCH, + BOCHSCPU_HOOK_TLB_CONTEXTSWITCH = BOCHSCPU_HOOK_TLB_CONTEXTSWITCH, + BOCHSCPU_HOOK_TLB_INVLPG = BOCHSCPU_HOOK_TLB_INVLPG, + BOCHSCPU_HOOK_TLB_INVEPT = BOCHSCPU_HOOK_TLB_INVEPT, + BOCHSCPU_HOOK_TLB_INVVPID = BOCHSCPU_HOOK_TLB_INVVPID, + BOCHSCPU_HOOK_TLB_INVPCID = BOCHSCPU_HOOK_TLB_INVPCID, +}; + + +enum class OpcodeOperationType +{ + BOCHSCPU_OPCODE_ERROR = BOCHSCPU_OPCODE_ERROR, + BOCHSCPU_OPCODE_INSERTED = BOCHSCPU_OPCODE_INSERTED, }; @@ -436,4 +444,35 @@ struct Session }; +struct Hook +{ + void* ctx {nullptr}; + std::function before_execution; + std::function after_execution; + std::function reset; + std::function hlt; + std::function mwait; + std::function cnear_branch_taken; + std::function cnear_branch_not_taken; + std::function ucnear_branch; + std::function far_branch; + std::function vmexit; + std::function interrupt; + std::function hw_interrupt; + std::function clflush; + std::function tlb_cntrl; + std::function cache_cntrl; + std::function prefetch_hint; + std::function wrmsr; + std::function repeat_iteration; + std::function lin_access; + std::function phy_access; + std::function inp; + std::function inp2; + std::function outp; + std::function opcode; + std::function exception; +}; + + } // namespace BochsCPU \ No newline at end of file diff --git a/python/src/bochscpu.cpp b/python/src/bochscpu.cpp index 35d555f..9df7d37 100644 --- a/python/src/bochscpu.cpp +++ b/python/src/bochscpu.cpp @@ -20,7 +20,7 @@ void bochscpu_cpu_module(nb::module_& m); -int +static int bochscpu_tp_traverse(PyObject* self, visitproc visit, void* arg) { BochsCPU::Session* sess = nb::inst_ptr(self); @@ -29,7 +29,7 @@ bochscpu_tp_traverse(PyObject* self, visitproc visit, void* arg) return 0; } -int +static int bochscpu_tp_clear(PyObject* self) { dbg("clearing PF handler"); @@ -45,78 +45,145 @@ PyType_Slot slots[] = { NB_MODULE(bochscpu, m) { + m.doc() = "The `bochscpu` module"; + // // Submodules // bochscpu_memory_module(m); bochscpu_cpu_module(m); - // - // Constants - // - m.attr("BX_INSTR_IS_JMP") = BX_INSTR_IS_JMP; - m.attr("BOCHSCPU_INSTR_IS_JMP_INDIRECT") = BOCHSCPU_INSTR_IS_JMP_INDIRECT; - m.attr("BOCHSCPU_INSTR_IS_CALL") = BOCHSCPU_INSTR_IS_CALL; - m.attr("BOCHSCPU_INSTR_IS_CALL_INDIRECT") = BOCHSCPU_INSTR_IS_CALL_INDIRECT; - m.attr("BOCHSCPU_INSTR_IS_RET") = BOCHSCPU_INSTR_IS_RET; - m.attr("BOCHSCPU_INSTR_IS_IRET") = BOCHSCPU_INSTR_IS_IRET; - m.attr("BOCHSCPU_INSTR_IS_INT") = BOCHSCPU_INSTR_IS_INT; - m.attr("BOCHSCPU_INSTR_IS_SYSCALL") = BOCHSCPU_INSTR_IS_SYSCALL; - m.attr("BOCHSCPU_INSTR_IS_SYSRET") = BOCHSCPU_INSTR_IS_SYSRET; - m.attr("BOCHSCPU_INSTR_IS_SYSENTER") = BOCHSCPU_INSTR_IS_SYSENTER; - m.attr("BOCHSCPU_INSTR_IS_SYSEXIT") = BOCHSCPU_INSTR_IS_SYSEXIT; - m.attr("BOCHSCPU_HOOK_MEM_READ") = BOCHSCPU_HOOK_MEM_READ; - m.attr("BOCHSCPU_HOOK_MEM_WRITE") = BOCHSCPU_HOOK_MEM_WRITE; - m.attr("BOCHSCPU_HOOK_MEM_EXECUTE") = BOCHSCPU_HOOK_MEM_EXECUTE; - m.attr("BOCHSCPU_HOOK_MEM_RW") = BOCHSCPU_HOOK_MEM_RW; - m.attr("BOCHSCPU_HOOK_TLB_CR0") = BOCHSCPU_HOOK_TLB_CR0; - m.attr("BOCHSCPU_HOOK_TLB_CR3") = BOCHSCPU_HOOK_TLB_CR3; - m.attr("BOCHSCPU_HOOK_TLB_CR4") = BOCHSCPU_HOOK_TLB_CR4; - m.attr("BOCHSCPU_HOOK_TLB_TASKSWITCH") = BOCHSCPU_HOOK_TLB_TASKSWITCH; - m.attr("BOCHSCPU_HOOK_TLB_CONTEXTSWITCH") = BOCHSCPU_HOOK_TLB_CONTEXTSWITCH; - m.attr("BOCHSCPU_HOOK_TLB_INVLPG") = BOCHSCPU_HOOK_TLB_INVLPG; - m.attr("BOCHSCPU_HOOK_TLB_INVEPT") = BOCHSCPU_HOOK_TLB_INVEPT; - m.attr("BOCHSCPU_HOOK_TLB_INVVPID") = BOCHSCPU_HOOK_TLB_INVVPID; - m.attr("BOCHSCPU_HOOK_TLB_INVPCID") = BOCHSCPU_HOOK_TLB_INVPCID; - m.attr("BOCHSCPU_OPCODE_ERROR") = BOCHSCPU_OPCODE_ERROR; - m.attr("BOCHSCPU_OPCODE_INSERTED") = BOCHSCPU_OPCODE_INSERTED; + nb::enum_(m, "InstructionType", "Class InstructionType") + .value("IS_JMP", BochsCPU::InstructionType::BX_INSTR_IS_JMP, "Constant value for BX_INSTR_IS_JMP") + .value( + "IS_JMP_INDIRECT", + BochsCPU::InstructionType::BOCHSCPU_INSTR_IS_JMP_INDIRECT, + "Constant value for BOCHSCPU_INSTR_IS_JMP_INDIRECT") + .value( + "IS_CALL", + BochsCPU::InstructionType::BOCHSCPU_INSTR_IS_CALL, + "Constant value for BOCHSCPU_INSTR_IS_CALL") + .value( + "IS_CALL_INDIRECT", + BochsCPU::InstructionType::BOCHSCPU_INSTR_IS_CALL_INDIRECT, + "Constant value for BOCHSCPU_INSTR_IS_CALL_INDIRECT") + .value("IS_RET", BochsCPU::InstructionType::BOCHSCPU_INSTR_IS_RET, "Constant value for BOCHSCPU_INSTR_IS_RET") + .value( + "IS_IRET", + BochsCPU::InstructionType::BOCHSCPU_INSTR_IS_IRET, + "Constant value for BOCHSCPU_INSTR_IS_IRET") + .value("IS_INT", BochsCPU::InstructionType::BOCHSCPU_INSTR_IS_INT, "Constant value for BOCHSCPU_INSTR_IS_INT") + .value( + "IS_SYSCALL", + BochsCPU::InstructionType::BOCHSCPU_INSTR_IS_SYSCALL, + "Constant value for BOCHSCPU_INSTR_IS_SYSCALL") + .value( + "IS_SYSRET", + BochsCPU::InstructionType::BOCHSCPU_INSTR_IS_SYSRET, + "Constant value for BOCHSCPU_INSTR_IS_SYSRET") + .value( + "IS_SYSENTER", + BochsCPU::InstructionType::BOCHSCPU_INSTR_IS_SYSENTER, + "Constant value for BOCHSCPU_INSTR_IS_SYSENTER") + .value( + "IS_SYSEXIT", + BochsCPU::InstructionType::BOCHSCPU_INSTR_IS_SYSEXIT, + "Constant value for BOCHSCPU_INSTR_IS_SYSEXIT") + .export_values(); + + + nb::enum_(m, "HookType", "Class HookType") + .value("MEM_READ", BochsCPU::HookType::BOCHSCPU_HOOK_MEM_READ, "Constant value for BOCHSCPU_HOOK_MEM_READ") + .value("MEM_WRITE", BochsCPU::HookType::BOCHSCPU_HOOK_MEM_WRITE, "Constant value for BOCHSCPU_HOOK_MEM_WRITE") + .value( + "MEM_EXECUTE", + BochsCPU::HookType::BOCHSCPU_HOOK_MEM_EXECUTE, + "Constant value for BOCHSCPU_HOOK_MEM_EXECUTE") + .value("MEM_RW", BochsCPU::HookType::BOCHSCPU_HOOK_MEM_RW, "Constant value for BOCHSCPU_HOOK_MEM_RW") + .value("TLB_CR0", BochsCPU::HookType::BOCHSCPU_HOOK_TLB_CR0, "Constant value for BOCHSCPU_HOOK_TLB_CR0") + .value("TLB_CR3", BochsCPU::HookType::BOCHSCPU_HOOK_TLB_CR3, "Constant value for BOCHSCPU_HOOK_TLB_CR3") + .value("TLB_CR4", BochsCPU::HookType::BOCHSCPU_HOOK_TLB_CR4, "Constant value for BOCHSCPU_HOOK_TLB_CR4") + .value( + "TLB_TASKSWITCH", + BochsCPU::HookType::BOCHSCPU_HOOK_TLB_TASKSWITCH, + "Constant value for BOCHSCPU_HOOK_TLB_TASKSWITCH") + .value( + "TLB_CONTEXTSWITCH", + BochsCPU::HookType::BOCHSCPU_HOOK_TLB_CONTEXTSWITCH, + "Constant value for BOCHSCPU_HOOK_TLB_CONTEXTSWITCH") + .value( + "TLB_INVLPG", + BochsCPU::HookType::BOCHSCPU_HOOK_TLB_INVLPG, + "Constant value for BOCHSCPU_HOOK_TLB_INVLPG") + .value( + "TLB_INVEPT", + BochsCPU::HookType::BOCHSCPU_HOOK_TLB_INVEPT, + "Constant value for BOCHSCPU_HOOK_TLB_INVEPT") + .value( + "TLB_INVVPID", + BochsCPU::HookType::BOCHSCPU_HOOK_TLB_INVVPID, + "Constant value for BOCHSCPU_HOOK_TLB_INVVPID") + .value( + "TLB_INVPCID", + BochsCPU::HookType::BOCHSCPU_HOOK_TLB_INVPCID, + "Constant value for BOCHSCPU_HOOK_TLB_INVPCID") + .export_values(); - nb::class_(m, "Hook") + + nb::enum_(m, "OpcodeOperationType", "Class OpcodeOperationType") + .value( + "OPERATION_ERROR", + BochsCPU::OpcodeOperationType::BOCHSCPU_OPCODE_ERROR, + "Constant value for BOCHSCPU_OPCODE_ERROR") + .value( + "OPERATION_INSERTED", + BochsCPU::OpcodeOperationType::BOCHSCPU_OPCODE_INSERTED, + "Constant value for BOCHSCPU_OPCODE_INSERTED") + .export_values(); + + + nb::class_(m, "Hook", "Class Hook") .def(nb::init<>()) - .def_rw("ctx", &BochsCPU::Hook::ctx) - .def_rw("reset", &BochsCPU::Hook::reset) - .def_rw("hlt", &BochsCPU::Hook::hlt) - .def_rw("mwait", &BochsCPU::Hook::mwait) - .def_rw("cnear_branch_taken", &BochsCPU::Hook::cnear_branch_taken) - .def_rw("cnear_branch_not_taken", &BochsCPU::Hook::cnear_branch_not_taken) - .def_rw("ucnear_branch", &BochsCPU::Hook::ucnear_branch) - .def_rw("far_branch", &BochsCPU::Hook::far_branch) - .def_rw("vmexit", &BochsCPU::Hook::vmexit) - .def_rw("interrupt", &BochsCPU::Hook::interrupt) - .def_rw("exception", &BochsCPU::Hook::exception) - .def_rw("hw_interrupt", &BochsCPU::Hook::hw_interrupt) - .def_rw("tlb_cntrl", &BochsCPU::Hook::tlb_cntrl) - .def_rw("cache_cntrl", &BochsCPU::Hook::cache_cntrl) - .def_rw("prefetch_hint", &BochsCPU::Hook::prefetch_hint) - .def_rw("clflush", &BochsCPU::Hook::clflush) - .def_rw("before_execution", &BochsCPU::Hook::before_execution) - .def_rw("after_execution", &BochsCPU::Hook::after_execution) - .def_rw("repeat_iteration", &BochsCPU::Hook::repeat_iteration) - .def_rw("lin_access", &BochsCPU::Hook::lin_access) - .def_rw("phy_access", &BochsCPU::Hook::phy_access) - .def_rw("wrmsr", &BochsCPU::Hook::wrmsr) - .def_rw("opcode", &BochsCPU::Hook::opcode) - .def_rw("inp", &BochsCPU::Hook::inp) - .def_rw("inp2", &BochsCPU::Hook::inp2) - .def_rw("outp", &BochsCPU::Hook::outp); + .def_rw("ctx", &BochsCPU::Hook::ctx, "A raw pointer to the Session object") + .def_rw("reset", &BochsCPU::Hook::reset, "Callback for Bochs `reset` callback") + .def_rw("hlt", &BochsCPU::Hook::hlt, "Callback for Bochs `hlt` callback") + .def_rw("mwait", &BochsCPU::Hook::mwait, "Callback for Bochs `mwait` callback") + .def_rw( + "cnear_branch_taken", + &BochsCPU::Hook::cnear_branch_taken, + "Callback for Bochs `cnear_branch_taken` callback") + .def_rw( + "cnear_branch_not_taken", + &BochsCPU::Hook::cnear_branch_not_taken, + "Callback for Bochs `cnear_branch_not_taken` callback") + .def_rw("ucnear_branch", &BochsCPU::Hook::ucnear_branch, "Callback for Bochs `ucnear_branch` callback") + .def_rw("far_branch", &BochsCPU::Hook::far_branch, "Callback for Bochs `far_branch` callback") + .def_rw("vmexit", &BochsCPU::Hook::vmexit, "Callback for Bochs `vmexit` callback") + .def_rw("interrupt", &BochsCPU::Hook::interrupt, "Callback for Bochs `interrupt` callback") + .def_rw("exception", &BochsCPU::Hook::exception, "Callback for Bochs `exception` callback") + .def_rw("hw_interrupt", &BochsCPU::Hook::hw_interrupt, "Callback for Bochs `hw_interrupt` callback") + .def_rw("tlb_cntrl", &BochsCPU::Hook::tlb_cntrl, "Callback for Bochs `tlb_cntrl` callback") + .def_rw("cache_cntrl", &BochsCPU::Hook::cache_cntrl, "Callback for Bochs `cache_cntrl` callback") + .def_rw("prefetch_hint", &BochsCPU::Hook::prefetch_hint, "Callback for Bochs `prefetch_hint` callback") + .def_rw("clflush", &BochsCPU::Hook::clflush, "Callback for Bochs `clflush` callback") + .def_rw("before_execution", &BochsCPU::Hook::before_execution, "Callback for Bochs `before_execution` callback") + .def_rw("after_execution", &BochsCPU::Hook::after_execution, "Callback for Bochs `after_execution` callback") + .def_rw("repeat_iteration", &BochsCPU::Hook::repeat_iteration, "Callback for Bochs `repeat_iteration` callback") + .def_rw("lin_access", &BochsCPU::Hook::lin_access, "Callback for Bochs `lin_access` callback") + .def_rw("phy_access", &BochsCPU::Hook::phy_access, "Callback for Bochs `phy_access` callback") + .def_rw("wrmsr", &BochsCPU::Hook::wrmsr, "Callback for Bochs `wrmsr` callback") + .def_rw("opcode", &BochsCPU::Hook::opcode, "Callback for Bochs `opcode` callback") + .def_rw("inp", &BochsCPU::Hook::inp, "Callback for Bochs `inp` callback") + .def_rw("inp2", &BochsCPU::Hook::inp2, "Callback for Bochs `inp2` callback") + .def_rw("outp", &BochsCPU::Hook::outp, "Callback for Bochs `outp` callback"); - nb::class_(m, "Segment") + nb::class_(m, "Segment", "Segment class") .def(nb::init<>()) - .def_rw("present", &Seg::present) - .def_rw("selector", &Seg::selector) - .def_rw("base", &Seg::base) - .def_rw("limit", &Seg::limit) - .def_rw("attr", &Seg::attr) + .def_rw("present", &Seg::present, "Get/Set the Segment `present` attribute") + .def_rw("selector", &Seg::selector, "Get/Set the Segment `selector` attribute") + .def_rw("base", &Seg::base, "Get/Set the Segment `base` attribute") + .def_rw("limit", &Seg::limit, "Get/Set the Segment `limit` attribute") + .def_rw("attr", &Seg::attr, "Get/Set the Segment `attr` attribute") .def( "__int__", [](Seg const& s) @@ -124,206 +191,174 @@ NB_MODULE(bochscpu, m) return s.selector; }); - nb::class_(m, "GlobalSegment") + nb::class_(m, "GlobalSegment", "GlobalSegment class") .def(nb::init<>()) - .def_rw("base", &GlobalSeg::base) - .def_rw("limit", &GlobalSeg::limit); + .def_rw("base", &GlobalSeg::base, "Get/Set the GlobalSegment `base` attribute") + .def_rw("limit", &GlobalSeg::limit, "Get/Set the GlobalSegment `limit` attribute"); nb::class_(m, "Zmm").def(nb::init<>()).def_rw("q", &Zmm::q); - nb::class_(m, "State", nb::type_slots(slots)) + nb::class_(m, "State", nb::type_slots(slots), "Class State") .def(nb::init<>()) - .def_rw("bochscpu_seed", &State::bochscpu_seed) - .def_rw("rax", &State::rax) - .def_rw("rcx", &State::rcx) - .def_rw("rdx", &State::rdx) - .def_rw("rbx", &State::rbx) - .def_rw("rsp", &State::rsp) - .def_rw("rbp", &State::rbp) - .def_rw("rsi", &State::rsi) - .def_rw("rdi", &State::rdi) - .def_rw("r8", &State::r8) - .def_rw("r9", &State::r9) - .def_rw("r10", &State::r10) - .def_rw("r11", &State::r11) - .def_rw("r12", &State::r12) - .def_rw("r13", &State::r13) - .def_rw("r14", &State::r14) - .def_rw("r15", &State::r15) - .def_rw("rip", &State::rip) - .def_rw("rflags", &State::rflags) - .def_rw("es", &State::es) - .def_rw("cs", &State::cs) - .def_rw("ss", &State::ss) - .def_rw("ds", &State::ds) - .def_rw("fs", &State::fs) - .def_rw("gs", &State::gs) - .def_rw("ldtr", &State::ldtr) - .def_rw("tr", &State::tr) - .def_rw("gdtr", &State::gdtr) - .def_rw("idtr", &State::idtr) - .def_rw("cr0", &State::cr0) - .def_rw("cr2", &State::cr2) - .def_rw("cr3", &State::cr3) - .def_rw("cr4", &State::cr4) - .def_rw("cr8", &State::cr8) - .def_rw("dr0", &State::dr0) - .def_rw("dr1", &State::dr1) - .def_rw("dr2", &State::dr2) - .def_rw("dr3", &State::dr3) - .def_rw("dr6", &State::dr6) - .def_rw("dr7", &State::dr7) - .def_rw("xcr0", &State::xcr0) - .def_rw("zmm", &State::zmm) - .def_rw("fpcw", &State::fpcw) - .def_rw("fpsw", &State::fpsw) - .def_rw("fptw", &State::fptw) - .def_rw("fpop", &State::fpop) - .def_rw("fpst", &State::fpst) - .def_rw("mxcsr", &State::mxcsr) - .def_rw("mxcsr_mask", &State::mxcsr_mask) - .def_rw("tsc", &State::tsc) - .def_rw("efer", &State::efer) - .def_rw("kernel_gs_base", &State::kernel_gs_base) - .def_rw("apic_base", &State::apic_base) - .def_rw("pat", &State::pat) - .def_rw("sysenter_cs", &State::sysenter_cs) - .def_rw("sysenter_eip", &State::sysenter_eip) - .def_rw("sysenter_esp", &State::sysenter_esp) - .def_rw("star", &State::star) - .def_rw("lstar", &State::lstar) - .def_rw("cstar", &State::cstar) - .def_rw("sfmask", &State::sfmask) - .def_rw("tsc_aux", &State::tsc_aux); + .def_rw("seed", &State::bochscpu_seed, "Get/Set the seed in the current state") + .def_rw("rax", &State::rax, "Get/Set the register `rax` in the current state") + .def_rw("rcx", &State::rcx, "Get/Set the register `rcx` in the current state") + .def_rw("rdx", &State::rdx, "Get/Set the register `rdx` in the current state") + .def_rw("rbx", &State::rbx, "Get/Set the register `rbx` in the current state") + .def_rw("rsp", &State::rsp, "Get/Set the register `rsp` in the current state") + .def_rw("rbp", &State::rbp, "Get/Set the register `rbp` in the current state") + .def_rw("rsi", &State::rsi, "Get/Set the register `rsi` in the current state") + .def_rw("rdi", &State::rdi, "Get/Set the register `rdi` in the current state") + .def_rw("r8", &State::r8, "Get/Set the register `r8` in the current state") + .def_rw("r9", &State::r9, "Get/Set the register `r9` in the current state") + .def_rw("r10", &State::r10, "Get/Set the register `r10` in the current state") + .def_rw("r11", &State::r11, "Get/Set the register `r11` in the current state") + .def_rw("r12", &State::r12, "Get/Set the register `r12` in the current state") + .def_rw("r13", &State::r13, "Get/Set the register `r13` in the current state") + .def_rw("r14", &State::r14, "Get/Set the register `r14` in the current state") + .def_rw("r15", &State::r15, "Get/Set the register `r15` in the current state") + .def_rw("rip", &State::rip, "Get/Set the register `rip` in the current state") + .def_rw("rflags", &State::rflags, "Get/Set the register `rflags` in the current state") + .def_rw("es", &State::es, "Get/Set the register `es` in the current state") + .def_rw("cs", &State::cs, "Get/Set the register `cs` in the current state") + .def_rw("ss", &State::ss, "Get/Set the register `ss` in the current state") + .def_rw("ds", &State::ds, "Get/Set the register `ds` in the current state") + .def_rw("fs", &State::fs, "Get/Set the register `fs` in the current state") + .def_rw("gs", &State::gs, "Get/Set the register `gs` in the current state") + .def_rw("ldtr", &State::ldtr, "Get/Set the register `ldtr` in the current state") + .def_rw("tr", &State::tr, "Get/Set the register `tr` in the current state") + .def_rw("gdtr", &State::gdtr, "Get/Set the register `gdtr` in the current state") + .def_rw("idtr", &State::idtr, "Get/Set the register `idtr` in the current state") + .def_rw("cr0", &State::cr0, "Get/Set the register `cr0` in the current state") + .def_rw("cr2", &State::cr2, "Get/Set the register `cr2` in the current state") + .def_rw("cr3", &State::cr3, "Get/Set the register `cr3` in the current state") + .def_rw("cr4", &State::cr4, "Get/Set the register `cr4` in the current state") + .def_rw("cr8", &State::cr8, "Get/Set the register `cr8` in the current state") + .def_rw("dr0", &State::dr0, "Get/Set the register `dr0` in the current state") + .def_rw("dr1", &State::dr1, "Get/Set the register `dr1` in the current state") + .def_rw("dr2", &State::dr2, "Get/Set the register `dr2` in the current state") + .def_rw("dr3", &State::dr3, "Get/Set the register `dr3` in the current state") + .def_rw("dr6", &State::dr6, "Get/Set the register `dr6` in the current state") + .def_rw("dr7", &State::dr7, "Get/Set the register `dr7` in the current state") + .def_rw("xcr0", &State::xcr0, "Get/Set the register `xcr0` in the current state") + .def_rw("zmm", &State::zmm, "Get/Set the register `zmm` in the current state") + .def_rw("fpcw", &State::fpcw, "Get/Set the register `fpcw` in the current state") + .def_rw("fpsw", &State::fpsw, "Get/Set the register `fpsw` in the current state") + .def_rw("fptw", &State::fptw, "Get/Set the register `fptw` in the current state") + .def_rw("fpop", &State::fpop, "Get/Set the register `fpop` in the current state") + .def_rw("fpst", &State::fpst, "Get/Set the register `fpst` in the current state") + .def_rw("mxcsr", &State::mxcsr, "Get/Set the register `mxcsr` in the current state") + .def_rw("mxcsr_mask", &State::mxcsr_mask, "Get/Set the register `mxcsr_mask` in the current state") + .def_rw("tsc", &State::tsc, "Get/Set the register `tsc` in the current state") + .def_rw("efer", &State::efer, "Get/Set the register `efer` in the current state") + .def_rw("kernel_gs_base", &State::kernel_gs_base, "Get/Set the register `kernel_gs_base` in the current state") + .def_rw("apic_base", &State::apic_base, "Get/Set the register `apic_base` in the current state") + .def_rw("pat", &State::pat, "Get/Set the register `pat` in the current state") + .def_rw("sysenter_cs", &State::sysenter_cs, "Get/Set the register `sysenter_cs` in the current state") + .def_rw("sysenter_eip", &State::sysenter_eip, "Get/Set the register `sysenter_eip` in the current state") + .def_rw("sysenter_esp", &State::sysenter_esp, "Get/Set the register `sysenter_esp` in the current state") + .def_rw("star", &State::star, "Get/Set the register `star` in the current state") + .def_rw("lstar", &State::lstar, "Get/Set the register `lstar` in the current state") + .def_rw("cstar", &State::cstar, "Get/Set the register `cstar` in the current state") + .def_rw("sfmask", &State::sfmask, "Get/Set the register `sfmask` in the current state") + .def_rw("tsc_aux", &State::tsc_aux, "Get/Set the register `tsc_aux` in the current state"); // - // Exported native functions + // Exported native constants & functions // { - m.def( - "bochscpu_mem_page_insert", - [](uint64_t gpa, uintptr_t hva) - { - dbg("mapping GPA=%#llx <-> HVA=%#llx", gpa, hva); - ::bochscpu_mem_page_insert(gpa, (uint8_t*)hva); - }, - "Map a GPA to a HVA"); - m.def("bochscpu_mem_page_remove", &bochscpu_mem_page_remove, "gpa"_a); - m.def( - "bochscpu_mem_phy_translate", - [](const uint64_t gpa) - { - return (uintptr_t)(::bochscpu_mem_phy_translate(gpa)); - }, - "gpa"_a); - m.def("bochscpu_mem_virt_translate", &bochscpu_mem_virt_translate, "cr3"_a, "gva"_a); - m.def( - "bochscpu_mem_phy_read", - [](uint64_t gpa, uintptr_t sz) -> std::vector - { - std::vector hva(sz); - ::bochscpu_mem_phy_read(gpa, hva.data(), hva.size()); - return hva; - }, - "gpa"_a, - "size"_a, - "Read from GPA"); - m.def( - "bochscpu_mem_phy_write", - [](uint64_t gpa, std::vector const& hva) - { - ::bochscpu_mem_phy_write(gpa, hva.data(), hva.size()); - }, - "gpa"_a, - "hva"_a, - "Write to GPA"); - m.def( - "bochscpu_mem_virt_write", - [](uint64_t cr3, uint64_t gva, std::vector const& hva) - { - return ::bochscpu_mem_virt_write(cr3, gva, hva.data(), hva.size()) == 0; - }, - "cr3"_a, - "gva"_a, - "hva"_a, - "Write to GVA"); - m.def( - "bochscpu_mem_virt_read", - [](uint64_t cr3, uint64_t gva, const uint64_t sz) -> std::vector - { - std::vector hva(sz); - if ( ::bochscpu_mem_virt_read(cr3, gva, hva.data(), hva.size()) ) - throw std::runtime_error("invalid access"); - return hva; - }, - "cr3"_a, - "gva"_a, - "sz"_a, - "Read from GVA"); - m.def("bochscpu_log_set_level", &bochscpu_log_set_level, "level"_a); + m.attr("BX_INSTR_IS_JMP") = BX_INSTR_IS_JMP; + m.attr("BOCHSCPU_INSTR_IS_JMP_INDIRECT") = BOCHSCPU_INSTR_IS_JMP_INDIRECT; + m.attr("BOCHSCPU_INSTR_IS_CALL") = BOCHSCPU_INSTR_IS_CALL; + m.attr("BOCHSCPU_INSTR_IS_CALL_INDIRECT") = BOCHSCPU_INSTR_IS_CALL_INDIRECT; + m.attr("BOCHSCPU_INSTR_IS_RET") = BOCHSCPU_INSTR_IS_RET; + m.attr("BOCHSCPU_INSTR_IS_IRET") = BOCHSCPU_INSTR_IS_IRET; + m.attr("BOCHSCPU_INSTR_IS_INT") = BOCHSCPU_INSTR_IS_INT; + m.attr("BOCHSCPU_INSTR_IS_SYSCALL") = BOCHSCPU_INSTR_IS_SYSCALL; + m.attr("BOCHSCPU_INSTR_IS_SYSRET") = BOCHSCPU_INSTR_IS_SYSRET; + m.attr("BOCHSCPU_INSTR_IS_SYSENTER") = BOCHSCPU_INSTR_IS_SYSENTER; + m.attr("BOCHSCPU_INSTR_IS_SYSEXIT") = BOCHSCPU_INSTR_IS_SYSEXIT; + m.attr("BOCHSCPU_HOOK_MEM_READ") = BOCHSCPU_HOOK_MEM_READ; + m.attr("BOCHSCPU_HOOK_MEM_WRITE") = BOCHSCPU_HOOK_MEM_WRITE; + m.attr("BOCHSCPU_HOOK_MEM_EXECUTE") = BOCHSCPU_HOOK_MEM_EXECUTE; + m.attr("BOCHSCPU_HOOK_MEM_RW") = BOCHSCPU_HOOK_MEM_RW; + m.attr("BOCHSCPU_HOOK_TLB_CR0") = BOCHSCPU_HOOK_TLB_CR0; + m.attr("BOCHSCPU_HOOK_TLB_CR3") = BOCHSCPU_HOOK_TLB_CR3; + m.attr("BOCHSCPU_HOOK_TLB_CR4") = BOCHSCPU_HOOK_TLB_CR4; + m.attr("BOCHSCPU_HOOK_TLB_TASKSWITCH") = BOCHSCPU_HOOK_TLB_TASKSWITCH; + m.attr("BOCHSCPU_HOOK_TLB_CONTEXTSWITCH") = BOCHSCPU_HOOK_TLB_CONTEXTSWITCH; + m.attr("BOCHSCPU_HOOK_TLB_INVLPG") = BOCHSCPU_HOOK_TLB_INVLPG; + m.attr("BOCHSCPU_HOOK_TLB_INVEPT") = BOCHSCPU_HOOK_TLB_INVEPT; + m.attr("BOCHSCPU_HOOK_TLB_INVVPID") = BOCHSCPU_HOOK_TLB_INVVPID; + m.attr("BOCHSCPU_HOOK_TLB_INVPCID") = BOCHSCPU_HOOK_TLB_INVPCID; + m.attr("BOCHSCPU_OPCODE_ERROR") = BOCHSCPU_OPCODE_ERROR; + m.attr("BOCHSCPU_OPCODE_INSERTED") = BOCHSCPU_OPCODE_INSERTED; + + m.def("bochscpu_log_set_level", &bochscpu_log_set_level, "level"_a, "Set verbosity level"); m.def("instr_bx_opcode", &bochscpu_instr_bx_opcode, "p"_a); m.def("instr_imm16", &bochscpu_instr_imm16, "p"_a); m.def("instr_imm32", &bochscpu_instr_imm32, "p"_a); m.def("instr_imm64", &bochscpu_instr_imm64, "p"_a); + } - - nb::class_(m, "session", nb::type_slots(slots)) - .def(nb::init<>()) - .def_rw("missing_page_handler", &BochsCPU::Session::missing_page_handler, "Set the missing page callback") - .def_ro("cpu", &BochsCPU::Session::cpu, "Get the CPU associated to the session") - .def( - "run", - [](BochsCPU::Session& s, std::vector& h) + nb::class_(m, "session", nb::type_slots(slots), "Class session") + .def(nb::init<>()) + .def_rw("missing_page_handler", &BochsCPU::Session::missing_page_handler, "Set the missing page callback") + .def_ro("cpu", &BochsCPU::Session::cpu, "Get the CPU associated to the session") + .def( + "run", + [](BochsCPU::Session& s, std::vector& h) + { + if ( h.size() > (MAX_HOOKS - 1) ) { - if ( h.size() > (MAX_HOOKS - 1) ) - throw std::runtime_error("Too many hooks"); - - bochscpu_hooks_t hooks[MAX_HOOKS] {}; - bochscpu_hooks_t* hooks2[MAX_HOOKS] {}; + throw std::runtime_error("Too many hooks."); + } - for ( int i = 0; BochsCPU::Hook & _h : h ) - { - _h.ctx = (void*)&s; - hooks[i].ctx = (void*)&_h; - hooks[i].before_execution = BochsCPU::Callbacks::before_execution_cb; - hooks[i].after_execution = BochsCPU::Callbacks::after_execution_cb; - hooks[i].reset = BochsCPU::Callbacks::reset_cb; - hooks[i].hlt = BochsCPU::Callbacks::hlt_cb; - hooks[i].mwait = BochsCPU::Callbacks::mwait_cb; - hooks[i].cnear_branch_taken = BochsCPU::Callbacks::cnear_branch_taken_cb; - hooks[i].cnear_branch_not_taken = BochsCPU::Callbacks::cnear_branch_not_taken_cb; - hooks[i].ucnear_branch = BochsCPU::Callbacks::ucnear_branch_cb; - hooks[i].far_branch = BochsCPU::Callbacks::far_branch_cb; - hooks[i].vmexit = BochsCPU::Callbacks::vmexit_cb; - hooks[i].interrupt = BochsCPU::Callbacks::interrupt_cb; - hooks[i].hw_interrupt = BochsCPU::Callbacks::hw_interrupt_cb; - hooks[i].clflush = BochsCPU::Callbacks::clflush_cb; - hooks[i].tlb_cntrl = BochsCPU::Callbacks::tlb_cntrl_cb; - hooks[i].cache_cntrl = BochsCPU::Callbacks::cache_cntrl_cb; - hooks[i].prefetch_hint = BochsCPU::Callbacks::prefetch_hint_cb; - hooks[i].wrmsr = BochsCPU::Callbacks::wrmsr_cb; - hooks[i].repeat_iteration = BochsCPU::Callbacks::repeat_iteration_cb; - hooks[i].lin_access = BochsCPU::Callbacks::lin_access_cb; - hooks[i].phy_access = BochsCPU::Callbacks::phy_access_cb; - hooks[i].inp = BochsCPU::Callbacks::inp_cb; - hooks[i].inp2 = BochsCPU::Callbacks::inp2_cb; - hooks[i].outp = BochsCPU::Callbacks::outp_cb; - hooks[i].opcode = BochsCPU::Callbacks::opcode_cb; - hooks[i].exception = BochsCPU::Callbacks::exception_cb; - hooks2[i] = &hooks[i]; - i++; - } + bochscpu_hooks_t hooks[MAX_HOOKS] {}; + bochscpu_hooks_t* hooks2[MAX_HOOKS] {}; - ::bochscpu_cpu_run(&s.cpu, hooks2); - }, - "Start the execution with a set of hooks") - .def( - "stop", - [](BochsCPU::Session& s) + for ( int i = 0; BochsCPU::Hook & _h : h ) { - ::bochscpu_cpu_stop(&s.cpu); - }, - "Stop the execution"); - } + _h.ctx = (void*)&s; + hooks[i].ctx = (void*)&_h; + hooks[i].before_execution = BochsCPU::Callbacks::before_execution_cb; + hooks[i].after_execution = BochsCPU::Callbacks::after_execution_cb; + hooks[i].reset = BochsCPU::Callbacks::reset_cb; + hooks[i].hlt = BochsCPU::Callbacks::hlt_cb; + hooks[i].mwait = BochsCPU::Callbacks::mwait_cb; + hooks[i].cnear_branch_taken = BochsCPU::Callbacks::cnear_branch_taken_cb; + hooks[i].cnear_branch_not_taken = BochsCPU::Callbacks::cnear_branch_not_taken_cb; + hooks[i].ucnear_branch = BochsCPU::Callbacks::ucnear_branch_cb; + hooks[i].far_branch = BochsCPU::Callbacks::far_branch_cb; + hooks[i].vmexit = BochsCPU::Callbacks::vmexit_cb; + hooks[i].interrupt = BochsCPU::Callbacks::interrupt_cb; + hooks[i].hw_interrupt = BochsCPU::Callbacks::hw_interrupt_cb; + hooks[i].clflush = BochsCPU::Callbacks::clflush_cb; + hooks[i].tlb_cntrl = BochsCPU::Callbacks::tlb_cntrl_cb; + hooks[i].cache_cntrl = BochsCPU::Callbacks::cache_cntrl_cb; + hooks[i].prefetch_hint = BochsCPU::Callbacks::prefetch_hint_cb; + hooks[i].wrmsr = BochsCPU::Callbacks::wrmsr_cb; + hooks[i].repeat_iteration = BochsCPU::Callbacks::repeat_iteration_cb; + hooks[i].lin_access = BochsCPU::Callbacks::lin_access_cb; + hooks[i].phy_access = BochsCPU::Callbacks::phy_access_cb; + hooks[i].inp = BochsCPU::Callbacks::inp_cb; + hooks[i].inp2 = BochsCPU::Callbacks::inp2_cb; + hooks[i].outp = BochsCPU::Callbacks::outp_cb; + hooks[i].opcode = BochsCPU::Callbacks::opcode_cb; + hooks[i].exception = BochsCPU::Callbacks::exception_cb; + hooks2[i] = &hooks[i]; + i++; + } + + ::bochscpu_cpu_run(&s.cpu, hooks2); + }, + "Start the execution with a set of hooks") + .def( + "stop", + [](BochsCPU::Session& s) + { + ::bochscpu_cpu_stop(&s.cpu); + }, + "Stop the execution"); } diff --git a/python/src/bochscpu_mem.cpp b/python/src/bochscpu_mem.cpp index fefe8d3..9f52656 100644 --- a/python/src/bochscpu_mem.cpp +++ b/python/src/bochscpu_mem.cpp @@ -29,6 +29,67 @@ bochscpu_memory_module(nb::module_& base_module) m.def("PageSize", &BochsCPU::Memory::PageSize); m.def("AlignAddressToPage", &BochsCPU::Memory::AlignAddressToPage); + m.def( + "page_insert", + [](uint64_t gpa, uintptr_t hva) + { + dbg("mapping GPA=%#llx <-> HVA=%#llx", gpa, hva); + ::bochscpu_mem_page_insert(gpa, (uint8_t*)hva); + }, + "Map a GPA to a HVA"); + m.def("page_remove", &bochscpu_mem_page_remove, "gpa"_a); + m.def( + "phy_translate", + [](const uint64_t gpa) + { + return (uintptr_t)(::bochscpu_mem_phy_translate(gpa)); + }, + "gpa"_a); + m.def("virt_translate", &bochscpu_mem_virt_translate, "cr3"_a, "gva"_a); + m.def( + "phy_read", + [](uint64_t gpa, uintptr_t sz) -> std::vector + { + std::vector hva(sz); + ::bochscpu_mem_phy_read(gpa, hva.data(), hva.size()); + return hva; + }, + "gpa"_a, + "size"_a, + "Read from GPA"); + m.def( + "phy_write", + [](uint64_t gpa, std::vector const& hva) + { + ::bochscpu_mem_phy_write(gpa, hva.data(), hva.size()); + }, + "gpa"_a, + "hva"_a, + "Write to GPA"); + m.def( + "virt_write", + [](uint64_t cr3, uint64_t gva, std::vector const& hva) + { + return ::bochscpu_mem_virt_write(cr3, gva, hva.data(), hva.size()) == 0; + }, + "cr3"_a, + "gva"_a, + "hva"_a, + "Write to GVA"); + m.def( + "virt_read", + [](uint64_t cr3, uint64_t gva, const uint64_t sz) -> std::vector + { + std::vector hva(sz); + if ( ::bochscpu_mem_virt_read(cr3, gva, hva.data(), hva.size()) ) + throw std::runtime_error("invalid access"); + return hva; + }, + "cr3"_a, + "gva"_a, + "sz"_a, + "Read from GVA"); + nb::class_(m, "PageMapLevel4Table") .def(nb::init<>()) .def("Translate", &BochsCPU::Memory::PageMapLevel4Table::Translate, "Translate a VA -> PA") From 627036b66cd09dc9d398f619991fd2b214ffa68b Mon Sep 17 00:00:00 2001 From: hugsy Date: Sat, 19 Aug 2023 18:06:41 -0700 Subject: [PATCH 02/11] added pyi --- python/stubs/bochscpu/__init__.pyi | 1359 ++++++++++++++++++++++++++++ python/stubs/bochscpu/cpu.pyi | 306 +++++++ python/stubs/bochscpu/memory.pyi | 62 ++ 3 files changed, 1727 insertions(+) create mode 100644 python/stubs/bochscpu/__init__.pyi create mode 100644 python/stubs/bochscpu/cpu.pyi create mode 100644 python/stubs/bochscpu/memory.pyi diff --git a/python/stubs/bochscpu/__init__.pyi b/python/stubs/bochscpu/__init__.pyi new file mode 100644 index 0000000..4ff6031 --- /dev/null +++ b/python/stubs/bochscpu/__init__.pyi @@ -0,0 +1,1359 @@ +from typing import Any, Callable, Optional, overload +from enum import Enum +import bochscpu + +class GlobalSegment: + """ + GlobalSegment class + """ + + def __init__(self) -> None: ... + @property + def base(self) -> int: + """ + Get the GlobalSegment `base` attribute + """ + ... + @base.setter + def base(self) -> int: + """ + Set the GlobalSegment `base` attribute + """ + ... + @property + def limit(self) -> int: + """ + Get the GlobalSegment `limit` attribute + """ + ... + @limit.setter + def limit(self) -> int: + """ + Set the GlobalSegment `limit` attribute + """ + ... + +class HookType(Enum): + """ + + """ + + MEM_EXECUTE: HookType + MEM_READ: HookType + MEM_RW: HookType + MEM_WRITE: HookType + TLB_CONTEXTSWITCH: HookType + TLB_CR0: HookType + TLB_CR3: HookType + TLB_CR4: HookType + TLB_INVEPT: HookType + TLB_INVLPG: HookType + TLB_INVPCID: HookType + TLB_INVVPID: HookType + TLB_TASKSWITCH: HookType + +class InstructionType(Enum): + IS_CALL: InstructionType + IS_CALL_INDIRECT: InstructionType + IS_INT: InstructionType + IS_IRET: InstructionType + IS_JMP: InstructionType + IS_JMP_INDIRECT: InstructionType + IS_RET: InstructionType + IS_SYSCALL: InstructionType + IS_SYSENTER: InstructionType + IS_SYSEXIT: InstructionType + IS_SYSRET: InstructionType + +class OpcodeOperationType(Enum): + OPERATION_ERROR: OpcodeOperationType + OPERATION_INSERTED: OpcodeOperationType + +class Segment: + """ + Segment class + """ + + def __init__(self) -> None: ... + @property + def attr(self) -> int: + """ + Get/Set the Segment `attr` attribute + """ + ... + @attr.setter + def attr(self) -> int: + """ + Get/Set the Segment `attr` attribute + """ + ... + @property + def base(self) -> int: + """ + Get/Set the Segment `base` attribute + """ + ... + @base.setter + def base(self) -> int: + """ + Get/Set the Segment `base` attribute + """ + ... + @property + def limit(self) -> int: + """ + Get/Set the Segment `limit` attribute + """ + ... + @limit.setter + def limit(self) -> int: + """ + Get/Set the Segment `limit` attribute + """ + ... + @property + def present(self) -> bool: + """ + Get/Set the Segment `present` attribute + """ + ... + @present.setter + def present(self) -> bool: + """ + Get/Set the Segment `present` attribute + """ + ... + @property + def selector(self) -> int: + """ + Get/Set the Segment `selector` attribute + """ + ... + @selector.setter + def selector(self) -> int: + """ + Get/Set the Segment `selector` attribute + """ + ... + +class State: + """ + Class State + """ + + def __init__(self) -> None: ... + @property + def apic_base(self) -> int: + """Get/Set the register `apic_base` in the current state""" + ... + @apic_base.setter + def apic_base(self) -> int: + """Get/Set the register `apic_base` in the current state""" + ... + @property + def cr0(self) -> int: + """Get/Set the register `cr0` in the current state""" + ... + @cr0.setter + def cr0(self) -> int: + """Get/Set the register `cr0` in the current state""" + ... + @property + def cr2(self) -> int: + """Get/Set the register `cr2` in the current state""" + ... + @cr2.setter + def cr2(self) -> int: + """Get/Set the register `cr2` in the current state""" + ... + @property + def cr3(self) -> int: + """Get/Set the register `cr3` in the current state""" + ... + @cr3.setter + def cr3(self) -> int: + """Get/Set the register `cr3` in the current state""" + ... + @property + def cr4(self) -> int: + """Get/Set the register `cr4` in the current state""" + ... + @cr4.setter + def cr4(self) -> int: + """Get/Set the register `cr4` in the current state""" + ... + @property + def cr8(self) -> int: + """Get/Set the register `cr8` in the current state""" + ... + @cr8.setter + def cr8(self) -> int: + """Get/Set the register `cr8` in the current state""" + ... + @property + def cs(self) -> bochscpu.Segment: + """Get/Set the register `cs` in the current state""" + ... + @cs.setter + def cs(self) -> bochscpu.Segment: + """Get/Set the register `cs` in the current state""" + ... + @property + def cstar(self) -> int: + """Get/Set the register `cstar` in the current state""" + ... + @cstar.setter + def cstar(self) -> int: + """Get/Set the register `cstar` in the current state""" + ... + @property + def dr0(self) -> int: + """Get/Set the register `dr0` in the current state""" + ... + @dr0.setter + def dr0(self) -> int: + """ + Get + /Set the register `dr0` in the current state + """ + ... + @property + def dr1(self) -> int: + """ + Get + /Set the register `dr1` in the current state + """ + ... + @dr1.setter + def dr1(self) -> int: + """ + Get + /Set the register `dr1` in the current state + """ + ... + @property + def dr2(self) -> int: + """ + Get + /Set the register `dr2` in the current state + """ + ... + @dr2.setter + def dr2(self) -> int: + """ + Get + /Set the register `dr2` in the current state + """ + ... + @property + def dr3(self) -> int: + """ + Get + /Set the register `dr3` in the current state + """ + ... + @dr3.setter + def dr3(self) -> int: + """ + Get + /Set the register `dr3` in the current state + """ + ... + @property + def dr6(self) -> int: + """ + Get + /Set the register `dr6` in the current state + """ + ... + @dr6.setter + def dr6(self) -> int: + """ + Get + /Set the register `dr6` in the current state + """ + ... + @property + def dr7(self) -> int: + """ + Get + /Set the register `dr7` in the current state + """ + ... + @dr7.setter + def dr7(self) -> int: + """ + Get + /Set the register `dr7` in the current state + """ + ... + @property + def ds(self) -> bochscpu.Segment: + """ + Get + /Set the register `ds` in the current state + """ + ... + @ds.setter + def ds(self) -> bochscpu.Segment: + """ + + Get/Set the register `ds` in the current state + """ + ... + @property + def efer(self) -> int: + """ + + Get/Set the register `efer` in the current state + """ + ... + @efer.setter + def efer(self) -> int: + """ + + Get/Set the register `efer` in the current state + """ + ... + @property + def es(self) -> bochscpu.Segment: + """ + + Get/Set the register `es` in the current state + """ + ... + @es.setter + def es(self) -> bochscpu.Segment: + """ + + Get/Set the register `es` in the current state + """ + ... + @property + def fpcw(self) -> int: + """ + + Get/Set the register `fpcw` in the current state + """ + ... + @fpcw.setter + def fpcw(self) -> int: + """ + + Get/Set the register `fpcw` in the current state + """ + ... + @property + def fpop(self) -> int: + """ + + Get/Set the register `fpop` in the current state + """ + ... + @fpop.setter + def fpop(self) -> int: + """ + + Get/Set the register `fpop` in the current state + """ + ... + @property + def fpst(self) -> list[int]: + """ + + Get/Set the register `fpst` in the current state + """ + ... + @fpst.setter + def fpst(self) -> list[int]: + """ + + Get/Set the register `fpst` in the current state + """ + ... + @property + def fpsw(self) -> int: + """ + + Get/Set the register `fpsw` in the current state + """ + ... + @fpsw.setter + def fpsw(self) -> int: + """ + + Get/Set the register `fpsw` in the current state + """ + ... + @property + def fptw(self) -> int: + """ + + Get/Set the register `fptw` in the current state + """ + ... + @fptw.setter + def fptw(self) -> int: + """ + + Get/Set the register `fptw` in the current state + """ + ... + @property + def fs(self) -> bochscpu.Segment: + """ + + Get/Set the register `fs` in the current state + """ + ... + @fs.setter + def fs(self) -> bochscpu.Segment: + """ + + Get/Set the register `fs` in the current state + """ + ... + @property + def gdtr(self) -> bochscpu.GlobalSegment: + """ + + Get/Set the register `gdtr` in the current state + """ + ... + @gdtr.setter + def gdtr(self) -> bochscpu.GlobalSegment: + """ + + Get/Set the register `gdtr` in the current state + """ + ... + @property + def gs(self) -> bochscpu.Segment: + """ + + Get/Set the register `gs` in the current state + """ + ... + @gs.setter + def gs(self) -> bochscpu.Segment: + """ + + Get/Set the register `gs` in the current state + """ + ... + @property + def idtr(self) -> bochscpu.GlobalSegment: + """ + + Get/Set the register `idtr` in the current state + """ + ... + @idtr.setter + def idtr(self) -> bochscpu.GlobalSegment: + """ + + Get/Set the register `idtr` in the current state + """ + ... + @property + def kernel_gs_base(self) -> int: + """ + + Get/Set the register `kernel_gs_base` in the current state + """ + ... + @kernel_gs_base.setter + def kernel_gs_base(self) -> int: + """ + + Get/Set the register `kernel_gs_base` in the current state + """ + ... + @property + def ldtr(self) -> bochscpu.Segment: + """ + + Get/Set the register `ldtr` in the current state + """ + ... + @ldtr.setter + def ldtr(self) -> bochscpu.Segment: + """ + + Get/Set the register `ldtr` in the current state + """ + ... + @property + def lstar(self) -> int: + """ + + Get/Set the register `lstar` in the current state + """ + ... + @lstar.setter + def lstar(self) -> int: + """ + + Get/Set the register `lstar` in the current state + """ + ... + @property + def mxcsr(self) -> int: + """ + + Get/Set the register `mxcsr` in the current state + """ + ... + @mxcsr.setter + def mxcsr(self) -> int: + """ + + Get/Set the register `mxcsr` in the current state + """ + ... + @property + def mxcsr_mask(self) -> int: + """ + + Get/Set the register `mxcsr_mask` in the current state + """ + ... + @mxcsr_mask.setter + def mxcsr_mask(self) -> int: + """ + + Get/Set the register `mxcsr_mask` in the current state + """ + ... + @property + def pat(self) -> int: + """ + + Get/Set the register `pat` in the current state + """ + ... + @pat.setter + def pat(self) -> int: + """ + + Get/Set the register `pat` in the current state + """ + ... + @property + def r10(self) -> int: + """ + + Get/Set the register `r10` in the current state + """ + ... + @r10.setter + def r10(self) -> int: + """ + + Get/Set the register `r10` in the current state + """ + ... + @property + def r11(self) -> int: + """ + + Get/Set the register `r11` in the current state + """ + ... + @r11.setter + def r11(self) -> int: + """ + + Get/Set the register `r11` in the current state + """ + ... + @property + def r12(self) -> int: + """ + + Get/Set the register `r12` in the current state + """ + ... + @r12.setter + def r12(self) -> int: + """ + + Get/Set the register `r12` in the current state + """ + ... + @property + def r13(self) -> int: + """ + + Get/Set the register `r13` in the current state + """ + ... + @r13.setter + def r13(self) -> int: + """ + + Get/Set the register `r13` in the current state + """ + ... + @property + def r14(self) -> int: + """ + + Get/Set the register `r14` in the current state + """ + ... + @r14.setter + def r14(self) -> int: + """ + + Get/Set the register `r14` in the current state + """ + ... + @property + def r15(self) -> int: + """ + + Get/Set the register `r15` in the current state + """ + ... + @r15.setter + def r15(self) -> int: + """ + + Get/Set the register `r15` in the current state + """ + ... + @property + def r8(self) -> int: + """ + + Get/Set the register `r8` in the current state + """ + ... + @r8.setter + def r8(self) -> int: + """ + + Get/Set the register `r8` in the current state + """ + ... + @property + def r9(self) -> int: + """ + + Get/Set the register `r9` in the current state + """ + ... + @r9.setter + def r9(self) -> int: + """ + + Get/Set the register `r9` in the current state + """ + ... + @property + def rax(self) -> int: + """ + + Get/Set the register `rax` in the current state + """ + ... + @rax.setter + def rax(self) -> int: + """ + + Get/Set the register `rax` in the current state + """ + ... + @property + def rbp(self) -> int: + """ + + Get/Set the register `rbp` in the current state + """ + ... + @rbp.setter + def rbp(self) -> int: + """ + + Get/Set the register `rbp` in the current state + """ + ... + @property + def rbx(self) -> int: + """ + + Get/Set the register `rbx` in the current state + """ + ... + @rbx.setter + def rbx(self) -> int: + """ + + Get/Set the register `rbx` in the current state + """ + ... + @property + def rcx(self) -> int: + """ + + Get/Set the register `rcx` in the current state + """ + ... + @rcx.setter + def rcx(self) -> int: + """ + + Get/Set the register `rcx` in the current state + """ + ... + @property + def rdi(self) -> int: + """ + + Get/Set the register `rdi` in the current state + """ + ... + @rdi.setter + def rdi(self) -> int: + """ + + Get/Set the register `rdi` in the current state + """ + ... + @property + def rdx(self) -> int: + """ + + Get/Set the register `rdx` in the current state + """ + ... + @rdx.setter + def rdx(self) -> int: + """ + + Get/Set the register `rdx` in the current state + """ + ... + @property + def rflags(self) -> int: + """ + + Get/Set the register `rflags` in the current state + """ + ... + @rflags.setter + def rflags(self) -> int: + """ + + Get/Set the register `rflags` in the current state + """ + ... + @property + def rip(self) -> int: + """ + + Get/Set the register `rip` in the current state + """ + ... + @rip.setter + def rip(self) -> int: + """ + + Get/Set the register `rip` in the current state + """ + ... + @property + def rsi(self) -> int: + """ + + Get/Set the register `rsi` in the current state + """ + ... + @rsi.setter + def rsi(self) -> int: + """ + + Get/Set the register `rsi` in the current state + """ + ... + @property + def rsp(self) -> int: + """ + + Get/Set the register `rsp` in the current state + """ + ... + @rsp.setter + def rsp(self) -> int: + """ + + Get/Set the register `rsp` in the current state + """ + ... + @property + def seed(self) -> int: + """ + + Get/Set the seed in the current state + """ + ... + @seed.setter + def seed(self) -> int: + """ + + Get/Set the seed in the current state + """ + ... + @property + def sfmask(self) -> int: + """ + + Get/Set the register `sfmask` in the current state + """ + ... + @sfmask.setter + def sfmask(self) -> int: + """ + + Get/Set the register `sfmask` in the current state + """ + ... + @property + def ss(self) -> bochscpu.Segment: + """ + + Get/Set the register `ss` in the current state + """ + ... + @ss.setter + def ss(self) -> bochscpu.Segment: + """ + + Get/Set the register `ss` in the current state + """ + ... + @property + def star(self) -> int: + """ + + Get/Set the register `star` in the current state + """ + ... + @star.setter + def star(self) -> int: + """ + + Get/Set the register `star` in the current state + """ + ... + @property + def sysenter_cs(self) -> int: + """ + + Get/Set the register `sysenter_cs` in the current state + """ + ... + @sysenter_cs.setter + def sysenter_cs(self) -> int: + """ + + Get/Set the register `sysenter_cs` in the current state + """ + ... + @property + def sysenter_eip(self) -> int: + """ + + Get/Set the register `sysenter_eip` in the current state + """ + ... + @sysenter_eip.setter + def sysenter_eip(self) -> int: + """ + + Get/Set the register `sysenter_eip` in the current state + """ + ... + @property + def sysenter_esp(self) -> int: + """ + + Get/Set the register `sysenter_esp` in the current state + """ + ... + @sysenter_esp.setter + def sysenter_esp(self) -> int: + """ + + Get/Set the register `sysenter_esp` in the current state + """ + ... + @property + def tr(self) -> bochscpu.Segment: + """ + + Get/Set the register `tr` in the current state + """ + ... + @tr.setter + def tr(self) -> bochscpu.Segment: + """ + + Get/Set the register `tr` in the current state + """ + ... + @property + def tsc(self) -> int: + """ + + Get/Set the register `tsc` in the current state + """ + ... + @tsc.setter + def tsc(self) -> int: + """ + + Get/Set the register `tsc` in the current state + """ + ... + @property + def tsc_aux(self) -> int: + """ + + Get/Set the register `tsc_aux` in the current state + """ + ... + @tsc_aux.setter + def tsc_aux(self) -> int: + """ + + Get/Set the register `tsc_aux` in the current state + """ + ... + @property + def xcr0(self) -> int: + """ + + Get/Set the register `xcr0` in the current state + """ + ... + @xcr0.setter + def xcr0(self) -> int: + """ + + Get/Set the register `xcr0` in the current state + """ + ... + @property + def zmm(self) -> list[bochscpu.Zmm]: + """ + + Get/Set the register `zmm` in the current state + """ + ... + @zmm.setter + def zmm(self) -> list[bochscpu.Zmm]: + """ + + Get/Set the register `zmm` in the current state + """ + ... + +TLB_CONTEXTSWITCH: HookType +TLB_CR0: HookType +TLB_CR3: HookType +TLB_CR4: HookType +TLB_INVEPT: HookType +TLB_INVLPG: HookType +TLB_INVPCID: HookType +TLB_INVVPID: HookType +TLB_TASKSWITCH: HookType + +class Zmm: + def __init__(self) -> None: ... + @property + def q(self) -> list[int]: ... + @q.setter + def q(self) -> list[int]: ... + +def bochscpu_log_set_level(level: int) -> None: + """ + Set verbosity level + """ + ... + +def instr_bx_opcode(p: int) -> int: ... +def instr_imm16(p: int) -> int: ... +def instr_imm32(p: int) -> int: ... +def instr_imm64(p: int) -> int: ... + +class session: + """ + Class session + """ + + def __init__(self) -> None: ... + @property + def cpu(self) -> bochscpu.cpu.cpu: + """ + Get the CPU associated to the session + """ + ... + @property + def missing_page_handler(self) -> Callable[[int, None], None]: + """ + Set the missing page callback + """ + ... + @missing_page_handler.setter + def missing_page_handler(self) -> Callable[[int, None], None]: + """ + Get the missing page callback + """ + ... + def run(self, arg: list[bochscpu.Hook], /) -> None: + """ + Start the execution with a set of hooks + """ + ... + def stop(self) -> None: + """ + Stop the execution + """ + ... + +class Hook: + """ + Class Hook + """ + + def __init__(self) -> None: ... + @property + def after_execution(self) -> Callable[[bochscpu.session, int, int], None]: + """ + Callback for Bochs `after_execution` callback + """ + ... + @after_execution.setter + def after_execution(self) -> Callable[[bochscpu.session, int, int], None]: + """ + Callback for Bochs `after_execution` callback + """ + ... + @property + def before_execution(self) -> Callable[[bochscpu.session, int, int], None]: + """ + Callback for Bochs `before_execution` callback + """ + ... + @before_execution.setter + def before_execution(self) -> Callable[[bochscpu.session, int, int], None]: + """ + Callback for Bochs `before_execution` callback + """ + ... + @property + def cache_cntrl(self) -> Callable[[bochscpu.session, int, int], None]: + """ + Callback for Bochs `cache_cntrl` callback + """ + ... + @cache_cntrl.setter + def cache_cntrl(self) -> Callable[[bochscpu.session, int, int], None]: + """ + Callback for Bochs `cache_cntrl` callback + """ + ... + @property + def clflush(self) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `clflush` callback + """ + ... + @clflush.setter + def clflush(self) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `clflush` callback + """ + ... + @property + def cnear_branch_not_taken( + self, + ) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `cnear_branch_not_taken` callback + """ + ... + @cnear_branch_not_taken.setter + def cnear_branch_not_taken( + self, + ) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `cnear_branch_not_taken` callback + """ + ... + @property + def cnear_branch_taken(self) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `cnear_branch_taken` callback + """ + ... + @cnear_branch_taken.setter + def cnear_branch_taken(self) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `cnear_branch_taken` callback + """ + ... + @property + def ctx(self) -> int: + """ + A raw pointer to the Session object + """ + ... + @ctx.setter + def ctx(self) -> int: + """ + A raw pointer to the Session object + """ + ... + @property + def exception(self) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `exception` callback + """ + ... + @exception.setter + def exception(self) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `exception` callback + """ + ... + @property + def far_branch( + self, + ) -> Callable[[bochscpu.session, int, int, int, int, int, int], None]: + """ + Callback for Bochs `far_branch` callback + """ + ... + @far_branch.setter + def far_branch( + self, + ) -> Callable[[bochscpu.session, int, int, int, int, int, int], None]: + """ + Callback for Bochs `far_branch` callback + """ + ... + @property + def hlt(self) -> Callable[[bochscpu.session, int], None]: + """ + Callback for Bochs `hlt` callback + """ + ... + @hlt.setter + def hlt(self) -> Callable[[bochscpu.session, int], None]: + """ + Callback for Bochs `hlt` callback + """ + ... + @property + def hw_interrupt(self) -> Callable[[bochscpu.session, int, int, int, int], None]: + """ + Callback for Bochs `hw_interrupt` callback + """ + ... + @hw_interrupt.setter + def hw_interrupt(self) -> Callable[[bochscpu.session, int, int, int, int], None]: + """ + Callback for Bochs `hw_interrupt` callback + """ + ... + @property + def inp(self) -> Callable[[bochscpu.session, int, int], None]: + """ + Callback for Bochs `inp` callback + """ + ... + @inp.setter + def inp(self) -> Callable[[bochscpu.session, int, int], None]: + """ + Callback for Bochs `inp` callback + """ + ... + @property + def inp2(self) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `inp2` callback + """ + ... + @inp2.setter + def inp2(self) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `inp2` callback + """ + ... + @property + def interrupt(self) -> Callable[[bochscpu.session, int, int], None]: + """ + Callback for Bochs `interrupt` callback + """ + ... + @interrupt.setter + def interrupt(self) -> Callable[[bochscpu.session, int, int], None]: + """ + Callback for Bochs `interrupt` callback + """ + ... + @property + def lin_access( + self, + ) -> Callable[[bochscpu.session, int, int, int, int, int, int], None]: + """ + Callback for Bochs `lin_access` callback + """ + ... + @lin_access.setter + def lin_access( + self, + ) -> Callable[[bochscpu.session, int, int, int, int, int, int], None]: + """ + Callback for Bochs `lin_access` callback + """ + ... + @property + def mwait(self) -> Callable[[bochscpu.session, int, int, int, int], None]: + """ + Callback for Bochs `mwait` callback + """ + ... + @mwait.setter + def mwait(self) -> Callable[[bochscpu.session, int, int, int, int], None]: + """ + Callback for Bochs `mwait` callback + """ + ... + @property + def opcode( + self, + ) -> Callable[[bochscpu.session, int, int, int, int, bool, bool], None]: + """ + Callback for Bochs `opcode` callback + """ + ... + @opcode.setter + def opcode( + self, + ) -> Callable[[bochscpu.session, int, int, int, int, bool, bool], None]: + """ + Callback for Bochs `opcode` callback + """ + ... + @property + def outp(self) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `outp` callback + """ + ... + @outp.setter + def outp(self) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `outp` callback + """ + ... + @property + def phy_access(self) -> Callable[[bochscpu.session, int, int, int, int, int], None]: + """ + Callback for Bochs `phy_access` callback + """ + ... + @phy_access.setter + def phy_access(self) -> Callable[[bochscpu.session, int, int, int, int, int], None]: + """ + Callback for Bochs `phy_access` callback + """ + ... + @property + def prefetch_hint(self) -> Callable[[bochscpu.session, int, int, int, int], None]: + """ + Callback for Bochs `prefetch_hint` callback + """ + ... + @prefetch_hint.setter + def prefetch_hint(self) -> Callable[[bochscpu.session, int, int, int, int], None]: + """ + Callback for Bochs `prefetch_hint` callback + """ + ... + @property + def repeat_iteration(self) -> Callable[[bochscpu.session, int, int], None]: + """ + Callback for Bochs `repeat_iteration` callback + """ + ... + @repeat_iteration.setter + def repeat_iteration(self) -> Callable[[bochscpu.session, int, int], None]: + """ + Callback for Bochs `repeat_iteration` callback + """ + ... + @property + def reset(self) -> Callable[[bochscpu.session, int, int], None]: + """ + Callback for Bochs `reset` callback + """ + ... + @reset.setter + def reset(self) -> Callable[[bochscpu.session, int, int], None]: + """ + Callback for Bochs `reset` callback + """ + ... + @property + def tlb_cntrl(self) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `tlb_cntrl` callback + """ + ... + @tlb_cntrl.setter + def tlb_cntrl(self) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `tlb_cntrl` callback + """ + ... + @property + def ucnear_branch(self) -> Callable[[bochscpu.session, int, int, int, int], None]: + """ + Callback for Bochs `ucnear_branch` callback + """ + ... + @ucnear_branch.setter + def ucnear_branch(self) -> Callable[[bochscpu.session, int, int, int, int], None]: + """ + Callback for Bochs `ucnear_branch` callback + """ + ... + @property + def vmexit(self) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `vmexit` callback + """ + ... + @vmexit.setter + def vmexit(self) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `vmexit` callback + """ + ... + @property + def wrmsr(self) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `wrmsr` callback + """ + ... + @wrmsr.setter + def wrmsr(self) -> Callable[[bochscpu.session, int, int, int], None]: + """ + Callback for Bochs `wrmsr` callback + """ + ... diff --git a/python/stubs/bochscpu/cpu.pyi b/python/stubs/bochscpu/cpu.pyi new file mode 100644 index 0000000..44cb2fd --- /dev/null +++ b/python/stubs/bochscpu/cpu.pyi @@ -0,0 +1,306 @@ +import bochscpu.cpu + +class ControlRegister: + @property + def AM(self) -> bool: ... + @AM.setter + def AM(self) -> bool: ... + @property + def CD(self) -> bool: ... + @CD.setter + def CD(self) -> bool: ... + @property + def DE(self) -> bool: ... + @DE.setter + def DE(self) -> bool: ... + @property + def EM(self) -> bool: ... + @EM.setter + def EM(self) -> bool: ... + @property + def ET(self) -> bool: ... + @ET.setter + def ET(self) -> bool: ... + @property + def FSGSBASE(self) -> bool: ... + @FSGSBASE.setter + def FSGSBASE(self) -> bool: ... + @property + def MCE(self) -> bool: ... + @MCE.setter + def MCE(self) -> bool: ... + @property + def MP(self) -> bool: ... + @MP.setter + def MP(self) -> bool: ... + @property + def NE(self) -> bool: ... + @NE.setter + def NE(self) -> bool: ... + @property + def NW(self) -> bool: ... + @NW.setter + def NW(self) -> bool: ... + @property + def OSFXSR(self) -> bool: ... + @OSFXSR.setter + def OSFXSR(self) -> bool: ... + @property + def OSXMMEXCPT(self) -> bool: ... + @OSXMMEXCPT.setter + def OSXMMEXCPT(self) -> bool: ... + @property + def OSXSAVE(self) -> bool: ... + @OSXSAVE.setter + def OSXSAVE(self) -> bool: ... + @property + def PAE(self) -> bool: ... + @PAE.setter + def PAE(self) -> bool: ... + @property + def PCE(self) -> bool: ... + @PCE.setter + def PCE(self) -> bool: ... + @property + def PE(self) -> bool: ... + @PE.setter + def PE(self) -> bool: ... + @property + def PG(self) -> bool: ... + @PG.setter + def PG(self) -> bool: ... + @property + def PGE(self) -> bool: ... + @PGE.setter + def PGE(self) -> bool: ... + @property + def PSE(self) -> bool: ... + @PSE.setter + def PSE(self) -> bool: ... + @property + def PVI(self) -> bool: ... + @PVI.setter + def PVI(self) -> bool: ... + @property + def TS(self) -> bool: ... + @TS.setter + def TS(self) -> bool: ... + @property + def TSD(self) -> bool: ... + @TSD.setter + def TSD(self) -> bool: ... + @property + def VME(self) -> bool: ... + @VME.setter + def VME(self) -> bool: ... + @property + def WP(self) -> bool: ... + @WP.setter + def WP(self) -> bool: ... + def __init__(self) -> None: ... + +class ControlRegisterFlag: + """ + + """ + + AM: ControlRegisterFlag + CD: ControlRegisterFlag + DE: ControlRegisterFlag + EM: ControlRegisterFlag + ET: ControlRegisterFlag + FSGSBASE: ControlRegisterFlag + MCE: ControlRegisterFlag + MP: ControlRegisterFlag + NE: ControlRegisterFlag + NW: ControlRegisterFlag + OSFXSR: ControlRegisterFlag + OSXMMEXCPT: ControlRegisterFlag + OSXSAVE: ControlRegisterFlag + PAE: ControlRegisterFlag + PCE: ControlRegisterFlag + PE: ControlRegisterFlag + PG: ControlRegisterFlag + PGE: ControlRegisterFlag + PSE: ControlRegisterFlag + PVI: ControlRegisterFlag + TS: ControlRegisterFlag + TSD: ControlRegisterFlag + VME: ControlRegisterFlag + WP: ControlRegisterFlag + + def __init__(*args, **kwargs): + """ + Initialize self. See help(type(self)) for accurate signature. + """ + ... + +DE: ControlRegisterFlag + +FSGSBASE: ControlRegisterFlag + +MCE: ControlRegisterFlag + +NW: ControlRegisterFlag + +OSFXSR: ControlRegisterFlag + +OSXMMEXCPT: ControlRegisterFlag + +OSXSAVE: ControlRegisterFlag + +PAE: ControlRegisterFlag + +PCE: ControlRegisterFlag + +PG: ControlRegisterFlag + +PGE: ControlRegisterFlag + +PSE: ControlRegisterFlag + +PVI: ControlRegisterFlag + +TSD: ControlRegisterFlag + +VME: ControlRegisterFlag + +class cpu: + def __init__(*args, **kwargs): + """ + Initialize self. See help(type(self)) for accurate signature. + """ + ... + @property + def cr2(self) -> int: ... + @cr2.setter + def cr2(self) -> int: ... + @property + def cr3(self) -> int: ... + @cr3.setter + def cr3(self) -> int: ... + @property + def cs(self) -> bochscpu.Segment: ... + @cs.setter + def cs(self) -> bochscpu.Segment: ... + @property + def ds(self) -> bochscpu.Segment: ... + @ds.setter + def ds(self) -> bochscpu.Segment: ... + @property + def es(self) -> bochscpu.Segment: ... + @es.setter + def es(self) -> bochscpu.Segment: ... + @property + def fs(self) -> bochscpu.Segment: ... + @fs.setter + def fs(self) -> bochscpu.Segment: ... + @property + def gdtr(self) -> bochscpu.GlobalSegment: ... + @gdtr.setter + def gdtr(self) -> bochscpu.GlobalSegment: ... + @property + def gs(self) -> bochscpu.Segment: ... + @gs.setter + def gs(self) -> bochscpu.Segment: ... + @property + def id(self) -> int: ... + @property + def idtr(self) -> bochscpu.GlobalSegment: ... + @idtr.setter + def idtr(self) -> bochscpu.GlobalSegment: ... + @property + def ldtr(self) -> bochscpu.Segment: ... + @ldtr.setter + def ldtr(self) -> bochscpu.Segment: ... + @property + def r10(self) -> int: ... + @r10.setter + def r10(self) -> int: ... + @property + def r11(self) -> int: ... + @r11.setter + def r11(self) -> int: ... + @property + def r12(self) -> int: ... + @r12.setter + def r12(self) -> int: ... + @property + def r13(self) -> int: ... + @r13.setter + def r13(self) -> int: ... + @property + def r14(self) -> int: ... + @r14.setter + def r14(self) -> int: ... + @property + def r15(self) -> int: ... + @r15.setter + def r15(self) -> int: ... + @property + def r8(self) -> int: ... + @r8.setter + def r8(self) -> int: ... + @property + def r9(self) -> int: ... + @r9.setter + def r9(self) -> int: ... + @property + def rax(self) -> int: ... + @rax.setter + def rax(self) -> int: ... + @property + def rbp(self) -> int: ... + @rbp.setter + def rbp(self) -> int: ... + @property + def rbx(self) -> int: ... + @rbx.setter + def rbx(self) -> int: ... + @property + def rcx(self) -> int: ... + @rcx.setter + def rcx(self) -> int: ... + @property + def rdi(self) -> int: ... + @rdi.setter + def rdi(self) -> int: ... + @property + def rdx(self) -> int: ... + @rdx.setter + def rdx(self) -> int: ... + @property + def rflags(self) -> int: ... + @rflags.setter + def rflags(self) -> int: ... + @property + def rip(self) -> int: ... + @rip.setter + def rip(self) -> int: ... + @property + def rsi(self) -> int: ... + @rsi.setter + def rsi(self) -> int: ... + @property + def rsp(self) -> int: ... + @rsp.setter + def rsp(self) -> int: ... + def set_exception(self, vector: int, error: int) -> None: ... + def set_mode(self) -> None: ... + def set_state_no_flush(self, state: bochscpu.State) -> None: ... + @property + def ss(self) -> bochscpu.Segment: ... + @ss.setter + def ss(self) -> bochscpu.Segment: ... + @property + def state(self) -> bochscpu.State: ... + @state.setter + def state(self) -> bochscpu.State: ... + @property + def tr(self) -> bochscpu.Segment: ... + @tr.setter + def tr(self) -> bochscpu.Segment: ... + @property + def zmm(self) -> bochscpu.Zmm: ... + @zmm.setter + def zmm(self, arg: int, /) -> bochscpu.Zmm: ... diff --git a/python/stubs/bochscpu/memory.pyi b/python/stubs/bochscpu/memory.pyi new file mode 100644 index 0000000..4f3b3fb --- /dev/null +++ b/python/stubs/bochscpu/memory.pyi @@ -0,0 +1,62 @@ +from typing import Any, Optional, overload +from enum import Enum +import bochscpu.memory + +class AccessType(Enum): + Execute: AccessType + Read: AccessType + Write: AccessType + +def AlignAddressToPage(arg: int, /) -> int: ... + +class PageMapLevel4Table: + def Commit(self, arg: int, /) -> list[tuple[int, int]]: + """ + Commit the layout of the tree to memory + """ + ... + def Insert(self, arg0: int, arg1: int, arg2: int, /) -> None: + """ + Associate the VA to PA + """ + ... + def Translate(self, arg: int, /) -> Optional[int]: + """ + Translate a VA -> PA + """ + ... + def __init__(self) -> None: ... + +def PageSize() -> int: ... +def page_insert(arg0: int, arg1: int, /) -> None: + """ + Map a GPA to a HVA + """ + ... + +def page_remove(gpa: int) -> None: ... +def phy_read(gpa: int, size: int) -> list[int]: + """ + Read from GPA + """ + ... + +def phy_translate(gpa: int) -> int: ... +def phy_write(gpa: int, hva: list[int]) -> None: + """ + Write to GPA + """ + ... + +def virt_read(cr3: int, gva: int, sz: int) -> list[int]: + """ + Read from GVA + """ + ... + +def virt_translate(cr3: int, gva: int) -> int: ... +def virt_write(cr3: int, gva: int, hva: list[int]) -> bool: + """ + Write to GVA + """ + ... From c7e2af2ff5880c700e34a196a9e55072cae77c40 Mon Sep 17 00:00:00 2001 From: hugsy Date: Sun, 20 Aug 2023 08:06:23 -0700 Subject: [PATCH 03/11] [docs] finished cpu module pyi --- python/stubs/bochscpu/cpu.pyi | 379 +++++++++++++++++++++++++--------- 1 file changed, 285 insertions(+), 94 deletions(-) diff --git a/python/stubs/bochscpu/cpu.pyi b/python/stubs/bochscpu/cpu.pyi index 44cb2fd..7e25fea 100644 --- a/python/stubs/bochscpu/cpu.pyi +++ b/python/stubs/bochscpu/cpu.pyi @@ -1,133 +1,354 @@ +from enum import Flag import bochscpu.cpu class ControlRegister: + """ + ControlRegister class + """ + @property - def AM(self) -> bool: ... + def AM(self) -> bool: + """ + Get/Set AM control register flag: CR0 Alignment Mask R/W + """ + ... @AM.setter - def AM(self) -> bool: ... + def AM(self) -> bool: + """ + Get/Set AM control register flag: CR0 Alignment Mask R/W + """ + ... @property - def CD(self) -> bool: ... + def CD(self) -> bool: + """ + Get/Set CD control register flag: CR0 Cache Disable R/W + """ + ... @CD.setter - def CD(self) -> bool: ... + def CD(self) -> bool: + """ + Get/Set CD control register flag: CR0 Cache Disable R/W + """ + ... @property - def DE(self) -> bool: ... + def DE(self) -> bool: + """ + Get/Set DE control register flag: CR4 Debugging Extensions R/W + """ + ... @DE.setter - def DE(self) -> bool: ... + def DE(self) -> bool: + """ + Get/Set DE control register flag: CR4 Debugging Extensions R/W + """ + ... @property - def EM(self) -> bool: ... + def EM(self) -> bool: + """ + Get/Set EM control register flag: CR0 Emulation R/W + """ + ... @EM.setter - def EM(self) -> bool: ... + def EM(self) -> bool: + """ + Get/Set EM control register flag: CR0 Emulation R/W + """ + ... @property - def ET(self) -> bool: ... + def ET(self) -> bool: + """ + Get/Set ET control register flag: CR0 Extension Type R + """ + ... @ET.setter - def ET(self) -> bool: ... + def ET(self) -> bool: + """ + Get/Set ET control register flag: CR0 Extension Type R + """ + ... @property - def FSGSBASE(self) -> bool: ... + def FSGSBASE(self) -> bool: + """ + Get/Set FSGSBASE control register flag: CR4 Enable RDFSBASE, RDGSBASE, WRFSBASE, and WRGSBASE instructions R/W + """ + ... @FSGSBASE.setter - def FSGSBASE(self) -> bool: ... + def FSGSBASE(self) -> bool: + """ + Get/Set FSGSBASE control register flag: CR4 Enable RDFSBASE, RDGSBASE, WRFSBASE, and WRGSBASE instructions R/W + """ + ... @property - def MCE(self) -> bool: ... + def MCE(self) -> bool: + """ + Get/Set MCE control register flag: CR4 Machine Check Enable R/W + """ + ... @MCE.setter - def MCE(self) -> bool: ... + def MCE(self) -> bool: + """ + Get/Set MCE control register flag: CR4 Machine Check Enable R/W + """ + ... @property - def MP(self) -> bool: ... + def MP(self) -> bool: + """ + Get/Set MP control register flag: CR0 Monitor Coprocessor R/W + """ + ... @MP.setter - def MP(self) -> bool: ... + def MP(self) -> bool: + """ + Get/Set MP control register flag: CR0 Monitor Coprocessor R/W + """ + ... @property - def NE(self) -> bool: ... + def NE(self) -> bool: + """ + Get/Set NE control register flag: CR0 Numeric Error R/W + """ + ... @NE.setter - def NE(self) -> bool: ... + def NE(self) -> bool: + """ + Get/Set NE control register flag: CR0 Numeric Error R/W + """ + ... @property - def NW(self) -> bool: ... + def NW(self) -> bool: + """ + Get/Set NW control register flag: CR0 Not Writethrough R/W + """ + ... @NW.setter - def NW(self) -> bool: ... + def NW(self) -> bool: + """ + Get/Set NW control register flag: CR0 Not Writethrough R/W + """ + ... @property - def OSFXSR(self) -> bool: ... + def OSFXSR(self) -> bool: + """ + Get/Set OSFXSR control register flag: CR4 Operating System FXSAVE/FXRSTOR Support R/W + """ + ... @OSFXSR.setter - def OSFXSR(self) -> bool: ... + def OSFXSR(self) -> bool: + """ + Get/Set OSFXSR control register flag: CR4 Operating System FXSAVE/FXRSTOR Support R/W + """ + ... @property - def OSXMMEXCPT(self) -> bool: ... + def OSXMMEXCPT(self) -> bool: + """ + Get/Set OSXMMEXCPT control register flag: CR4 Operating System Unmasked Exception Support R/W + """ + ... @OSXMMEXCPT.setter - def OSXMMEXCPT(self) -> bool: ... + def OSXMMEXCPT(self) -> bool: + """ + Get/Set OSXMMEXCPT control register flag: CR4 Operating System Unmasked Exception Support R/W + """ + ... @property - def OSXSAVE(self) -> bool: ... + def OSXSAVE(self) -> bool: + """ + Get/Set OSXSAVE control register flag: CR4 XSAVE and Processor Extended States Enable Bit R/W + """ + ... @OSXSAVE.setter - def OSXSAVE(self) -> bool: ... + def OSXSAVE(self) -> bool: + """ + Get/Set OSXSAVE control register flag: CR4 XSAVE and Processor Extended States Enable Bit R/W + """ + ... @property - def PAE(self) -> bool: ... + def PAE(self) -> bool: + """ + Get/Set PAE control register flag: CR4 Physical-Address Extension R/W + """ + ... @PAE.setter - def PAE(self) -> bool: ... + def PAE(self) -> bool: + """ + Get/Set PAE control register flag: CR4 Physical-Address Extension R/W + """ + ... @property - def PCE(self) -> bool: ... + def PCE(self) -> bool: + """ + Get/Set PCE control register flag: CR4 Performance-Monitoring Counter Enable R/W + """ + ... @PCE.setter - def PCE(self) -> bool: ... + def PCE(self) -> bool: + """ + Get/Set PCE control register flag: CR4 Performance-Monitoring Counter Enable R/W + """ + ... @property - def PE(self) -> bool: ... + def PE(self) -> bool: + """ + Get/Set PE control register flag: CR0 Protection Enabled R/W + """ + ... @PE.setter - def PE(self) -> bool: ... + def PE(self) -> bool: + """ + Get/Set PE control register flag: CR0 Protection Enabled R/W + """ + ... @property - def PG(self) -> bool: ... + def PG(self) -> bool: + """ + Get/Set PG control register flag: CR0 Paging R/W + """ + ... @PG.setter - def PG(self) -> bool: ... + def PG(self) -> bool: + """ + Get/Set PG control register flag: CR0 Paging R/W + """ + ... @property - def PGE(self) -> bool: ... + def PGE(self) -> bool: + """ + Get/Set PGE control register flag: CR4 Page-Global Enable R/W + """ + ... @PGE.setter - def PGE(self) -> bool: ... + def PGE(self) -> bool: + """ + Get/Set PGE control register flag: CR4 Page-Global Enable R/W + """ + ... @property - def PSE(self) -> bool: ... + def PSE(self) -> bool: + """ + Get/Set PSE control register flag: CR4 Page Size Extensions R/W + """ + ... @PSE.setter - def PSE(self) -> bool: ... + def PSE(self) -> bool: + """ + Get/Set PSE control register flag: CR4 Page Size Extensions R/W + """ + ... @property - def PVI(self) -> bool: ... + def PVI(self) -> bool: + """ + Get/Set PVI control register flag: CR4 Protected-Mode Virtual Interrupts R/W + """ + ... @PVI.setter - def PVI(self) -> bool: ... + def PVI(self) -> bool: + """ + Get/Set PVI control register flag: CR4 Protected-Mode Virtual Interrupts R/W + """ + ... @property - def TS(self) -> bool: ... + def TS(self) -> bool: + """ + Get/Set TS control register flag: CR0 Task Switched R/W + """ + ... @TS.setter - def TS(self) -> bool: ... + def TS(self) -> bool: + """ + Get/Set TS control register flag: CR0 Task Switched R/W + """ + ... @property - def TSD(self) -> bool: ... + def TSD(self) -> bool: + """ + Get/Set TSD control register flag: CR4 Time Stamp Disable R/W + """ + ... @TSD.setter - def TSD(self) -> bool: ... + def TSD(self) -> bool: + """ + Get/Set TSD control register flag: CR4 Time Stamp Disable R/W + """ + ... @property - def VME(self) -> bool: ... + def VME(self) -> bool: + """ + Get/Set VME control register flag: CR4 Virtual-8086 Mode Extensions R/W + """ + ... @VME.setter - def VME(self) -> bool: ... + def VME(self) -> bool: + """ + Get/Set VME control register flag: CR4 Virtual-8086 Mode Extensions R/W + """ + ... @property - def WP(self) -> bool: ... + def WP(self) -> bool: + """ + Get/Set WP control register flag: CR0 Write Protect R/W + """ + ... @WP.setter - def WP(self) -> bool: ... + def WP(self) -> bool: + """ + Get/Set WP control register flag: CR0 Write Protect R/W + """ + ... def __init__(self) -> None: ... -class ControlRegisterFlag: +class ControlRegisterFlag(Flag): """ """ - AM: ControlRegisterFlag + PG: ControlRegisterFlag + """Paging R/W""" CD: ControlRegisterFlag - DE: ControlRegisterFlag - EM: ControlRegisterFlag + """Cache Disable R/W""" + NW: ControlRegisterFlag + """Not Writethrough R/W""" + AM: ControlRegisterFlag + """Alignment Mask R/W""" + WP: ControlRegisterFlag + """Write Protect R/W""" + NE: ControlRegisterFlag + """Numeric Error R/W""" ET: ControlRegisterFlag - FSGSBASE: ControlRegisterFlag - MCE: ControlRegisterFlag + """Extension Type R""" + TS: ControlRegisterFlag + """Task Switched R/W""" + EM: ControlRegisterFlag + """Emulation R/W""" MP: ControlRegisterFlag - NE: ControlRegisterFlag - NW: ControlRegisterFlag - OSFXSR: ControlRegisterFlag - OSXMMEXCPT: ControlRegisterFlag + """Monitor Coprocessor R/W""" + PE: ControlRegisterFlag + """Protection Enabled R/W""" OSXSAVE: ControlRegisterFlag - PAE: ControlRegisterFlag + """ XSAVE and Processor Extended States Enable Bit R/W """ + FSGSBASE: ControlRegisterFlag + """ Enable RDFSBASE, RDGSBASE, WRFSBASE, and WRGSBASE instructions R/W """ + OSXMMEXCPT: ControlRegisterFlag + """ Operating System Unmasked Exception Support R/W """ + OSFXSR: ControlRegisterFlag + """ Operating System FXSAVE/FXRSTOR Support R/W """ PCE: ControlRegisterFlag - PE: ControlRegisterFlag - PG: ControlRegisterFlag + """ Performance-Monitoring Counter Enable R/W """ PGE: ControlRegisterFlag + """ Page-Global Enable R/W """ + MCE: ControlRegisterFlag + """ Machine Check Enable R/W """ + PAE: ControlRegisterFlag + """ Physical-Address Extension R/W """ PSE: ControlRegisterFlag - PVI: ControlRegisterFlag - TS: ControlRegisterFlag + """ Page Size Extensions R/W """ + DE: ControlRegisterFlag + """ Debugging Extensions R/W """ TSD: ControlRegisterFlag + """ Time Stamp Disable R/W """ + PVI: ControlRegisterFlag + """ Protected-Mode Virtual Interrupts R/W """ VME: ControlRegisterFlag - WP: ControlRegisterFlag + """ Virtual-8086 Mode Extensions R/W """ def __init__(*args, **kwargs): """ @@ -135,36 +356,6 @@ class ControlRegisterFlag: """ ... -DE: ControlRegisterFlag - -FSGSBASE: ControlRegisterFlag - -MCE: ControlRegisterFlag - -NW: ControlRegisterFlag - -OSFXSR: ControlRegisterFlag - -OSXMMEXCPT: ControlRegisterFlag - -OSXSAVE: ControlRegisterFlag - -PAE: ControlRegisterFlag - -PCE: ControlRegisterFlag - -PG: ControlRegisterFlag - -PGE: ControlRegisterFlag - -PSE: ControlRegisterFlag - -PVI: ControlRegisterFlag - -TSD: ControlRegisterFlag - -VME: ControlRegisterFlag - class cpu: def __init__(*args, **kwargs): """ From e3ff18bfb676df6de88c2f02042b9adde774e4d0 Mon Sep 17 00:00:00 2001 From: hugsy Date: Sun, 20 Aug 2023 08:38:34 -0700 Subject: [PATCH 04/11] added rflags --- python/inc/bochscpu.hpp | 49 ++++++- python/src/bochscpu_cpu.cpp | 252 ++++++++++++++++++++++++++++++++++++ 2 files changed, 295 insertions(+), 6 deletions(-) diff --git a/python/inc/bochscpu.hpp b/python/inc/bochscpu.hpp index 2d4b1f7..31dbeee 100644 --- a/python/inc/bochscpu.hpp +++ b/python/inc/bochscpu.hpp @@ -186,13 +186,9 @@ exception_cb(context_t* ctx, uint32_t cpu_id, unsigned vector, unsigned error_co namespace Cpu { -struct ControlRegister : std::bitset<64> -{ -}; - enum class ControlRegisterFlag : uint64_t { - /// CR0 - 3.1.1 + /// CR0 - - AMD Manual Vol2 - 3.1.1 PG = 31, // Paging R/W CD = 30, // Cache Disable R/W NW = 29, // Not Writethrough R/W @@ -206,7 +202,7 @@ enum class ControlRegisterFlag : uint64_t PE = 0, // Protection Enabled R/W - /// CR4 - 3.7.1 + /// CR4 - - AMD Manual Vol2 - 3.7.1 OSXSAVE = 18, // XSAVE and Processor Extended States Enable Bit R/W FSGSBASE = 16, // Enable RDFSBASE, RDGSBASE, WRFSBASE, and WRGSBASE instructions R/W OSXMMEXCPT = 10, // Operating System Unmasked Exception Support R/W @@ -222,6 +218,47 @@ enum class ControlRegisterFlag : uint64_t VME = 0, // Virtual-8086 Mode Extensions R/W }; +enum class FlagRegisterFlag : uint64_t +{ + // RFLAGS - AMD Manual Vol2 - 3.8 + ID = 21, // ID Flag R/W + VIP = 20, // Virtual Interrupt Pending R/W + VIF = 19, // Virtual Interrupt Flag R/W + AC = 18, // Alignment Check R/W + VM = 17, // Virtual-8086 Mode R/W + RF = 16, // Resume Flag R/W + Reserved4 = 15, // Read as Zero + NT = 14, // Nested Task R/W + IOPL2 = 13, // IOPL I/O Privilege Level R/W + IOPL1 = 12, // IOPL I/O Privilege Level R/W + OF = 11, // Overflow Flag R/W + DF = 10, // Direction Flag R/W + IF = 9, // Interrupt Flag R/W + TF = 8, // Trap Flag R/W + SF = 7, // Sign Flag R/W + ZF = 6, // Zero Flag R/W + Reserved3 = 5, // Read as Zero + AF = 4, // Auxiliary Flag R/W + Reserved2 = 3, // Read as Zero + PF = 2, // Parity Flag R/W + Reserved1 = 1, // Read as One + CF = 0, // Carry Flag R/W +}; + + +struct ControlRegister : std::bitset<64> +{ +}; + + +struct FlagRegister : std::bitset<64> +{ + FlagRegister() + { + set((int)FlagRegisterFlag::Reserved1, true); + } +}; + static uint32_t g_sessionId {0}; diff --git a/python/src/bochscpu_cpu.cpp b/python/src/bochscpu_cpu.cpp index 66873f5..b0357a8 100644 --- a/python/src/bochscpu_cpu.cpp +++ b/python/src/bochscpu_cpu.cpp @@ -52,6 +52,31 @@ bochscpu_cpu_module(nb::module_& base_module) .value("VME", BochsCPU::Cpu::ControlRegisterFlag::VME, "Virtual-8086 Mode Extensions R/W") .export_values(); + nb::enum_(m, "FlagRegisterFlag") + .value("ID", BochsCPU::Cpu::FlagRegisterFlag::ID, "ID Flag R/W") + .value("VIP", BochsCPU::Cpu::FlagRegisterFlag::VIP, "Virtual Interrupt Pending R/W") + .value("VIF", BochsCPU::Cpu::FlagRegisterFlag::VIF, "Virtual Interrupt Flag R/W") + .value("AC", BochsCPU::Cpu::FlagRegisterFlag::AC, "Alignment Check R/W") + .value("VM", BochsCPU::Cpu::FlagRegisterFlag::VM, "Virtual-8086 Mode R/W") + .value("RF", BochsCPU::Cpu::FlagRegisterFlag::RF, "Resume Flag R/W") + .value("Reserved4", BochsCPU::Cpu::FlagRegisterFlag::Reserved4, "Read as Zero") + .value("NT", BochsCPU::Cpu::FlagRegisterFlag::NT, "Nested Task R/W") + .value("IOPL2", BochsCPU::Cpu::FlagRegisterFlag::IOPL2, "IOPL I/O Privilege Level R/W") + .value("IOPL1", BochsCPU::Cpu::FlagRegisterFlag::IOPL1, "IOPL I/O Privilege Level R/W") + .value("OF", BochsCPU::Cpu::FlagRegisterFlag::OF, "Overflow Flag R/W") + .value("DF", BochsCPU::Cpu::FlagRegisterFlag::DF, "Direction Flag R/W") + .value("IF", BochsCPU::Cpu::FlagRegisterFlag::IF, "Interrupt Flag R/W") + .value("TF", BochsCPU::Cpu::FlagRegisterFlag::TF, "Trap Flag R/W") + .value("SF", BochsCPU::Cpu::FlagRegisterFlag::SF, "Sign Flag R/W") + .value("ZF", BochsCPU::Cpu::FlagRegisterFlag::ZF, "Zero Flag R/W") + .value("Reserved3", BochsCPU::Cpu::FlagRegisterFlag::Reserved3, "Read as Zero") + .value("AF", BochsCPU::Cpu::FlagRegisterFlag::AF, "Auxiliary Flag R/W") + .value("Reserved2", BochsCPU::Cpu::FlagRegisterFlag::Reserved2, "Read as Zero") + .value("PF", BochsCPU::Cpu::FlagRegisterFlag::PF, "Parity Flag R/W") + .value("Reserved1", BochsCPU::Cpu::FlagRegisterFlag::Reserved1, "Read as One") + .value("CF", BochsCPU::Cpu::FlagRegisterFlag::CF, "Carry Flag R/W") + .export_values(); + nb::class_(m, "ControlRegister") .def(nb::init<>()) .def_prop_rw( @@ -308,6 +333,233 @@ bochscpu_cpu_module(nb::module_& base_module) return cr.to_ullong(); }); + + nb::class_(m, "FlagRegister") + .def(nb::init<>()) + .def_prop_rw( + "ID", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::ID); + }, + [](BochsCPU::Cpu::FlagRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::ID, onoff); + }, + "ID Flag R/W") + .def_prop_rw( + "VIP", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::VIP); + }, + [](BochsCPU::Cpu::FlagRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::VIP, onoff); + }, + "Virtual Interrupt Pending R/W") + .def_prop_rw( + "VIF", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::VIF); + }, + [](BochsCPU::Cpu::FlagRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::VIF, onoff); + }, + "Virtual Interrupt Flag R/W") + .def_prop_rw( + "AC", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::AC); + }, + [](BochsCPU::Cpu::FlagRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::AC, onoff); + }, + "Alignment Check R/W") + .def_prop_rw( + "VM", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::VM); + }, + [](BochsCPU::Cpu::FlagRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::VM, onoff); + }, + "Virtual-8086 Mode R/W") + .def_prop_rw( + "RF", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::RF); + }, + [](BochsCPU::Cpu::FlagRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::RF, onoff); + }, + "Resume Flag R/W") + .def_prop_ro( + "Reserved4", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::Reserved4); + }, + "Read as Zero") + .def_prop_rw( + "NT", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::NT); + }, + [](BochsCPU::Cpu::FlagRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::NT, onoff); + }, + "Nested Task R/W") + .def_prop_rw( + "IOPL", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return int(fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::IOPL2)) << 1 | + int(fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::IOPL1)) << 0; + }, + [](BochsCPU::Cpu::FlagRegister& fr, uint8_t iopl) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::IOPL2, iopl & 2); + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::IOPL1, iopl & 1); + }, + "IOPL I/O Privilege Level R/W") + .def_prop_rw( + "OF", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::OF); + }, + [](BochsCPU::Cpu::FlagRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::OF, onoff); + }, + "Overflow Flag R/W") + .def_prop_rw( + "DF", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::DF); + }, + [](BochsCPU::Cpu::FlagRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::DF, onoff); + }, + "Direction Flag R/W") + .def_prop_rw( + "IF", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::IF); + }, + [](BochsCPU::Cpu::FlagRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::IF, onoff); + }, + "Interrupt Flag R/W") + .def_prop_rw( + "TF", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::TF); + }, + [](BochsCPU::Cpu::FlagRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::TF, onoff); + }, + "Trap Flag R/W") + .def_prop_rw( + "SF", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::SF); + }, + [](BochsCPU::Cpu::FlagRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::SF, onoff); + }, + "Sign Flag R/W") + .def_prop_rw( + "ZF", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::ZF); + }, + [](BochsCPU::Cpu::FlagRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::ZF, onoff); + }, + "Zero Flag R/W") + .def_prop_ro( + "Reserved3", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::Reserved3); + }, + "Read as Zero") + .def_prop_rw( + "AF", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::AF); + }, + [](BochsCPU::Cpu::FlagRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::AF, onoff); + }, + "Auxiliary Flag R/W") + .def_prop_ro( + "Reserved2", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::Reserved2); + }, + "Read as Zero") + .def_prop_rw( + "PF", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::PF); + }, + [](BochsCPU::Cpu::FlagRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::PF, onoff); + }, + "Parity Flag R/W") + .def_prop_ro( + "Reserved1", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::Reserved1); + }, + "Read as One") + .def_prop_rw( + "CF", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FlagRegisterFlag::CF); + }, + [](BochsCPU::Cpu::FlagRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FlagRegisterFlag::CF, onoff); + }, + "Carry Flag R/W") + .def( + "__int__", + [](BochsCPU::Cpu::FlagRegister& fr) + { + return fr.to_ullong(); + }); + nb::class_(m, "cpu") .def_ro("id", &BochsCPU::Cpu::CPU::id) From 79f0574b6f9ac8e6dd7edc72b31a2b7dcb425866 Mon Sep 17 00:00:00 2001 From: hugsy Date: Sun, 20 Aug 2023 08:46:34 -0700 Subject: [PATCH 05/11] added extended feature register --- python/inc/bochscpu.hpp | 15 +++++ python/src/bochscpu_cpu.cpp | 113 +++++++++++++++++++++++++++++++++++- 2 files changed, 127 insertions(+), 1 deletion(-) diff --git a/python/inc/bochscpu.hpp b/python/inc/bochscpu.hpp index 31dbeee..deec650 100644 --- a/python/inc/bochscpu.hpp +++ b/python/inc/bochscpu.hpp @@ -245,6 +245,17 @@ enum class FlagRegisterFlag : uint64_t CF = 0, // Carry Flag R/W }; +enum class FeatureRegisterFlag : uint64_t +{ + TCE = 15, // Translation Cache Extension R/W + FFXSR = 14, // Fast FXSAVE/FXRSTOR R/W + LMSLE = 13, // Long Mode Segment Limit Enable R/W + SVME = 12, // Secure Virtual Machine Enable R/W + NXE = 11, // No-Execute Enable R/W + LMA = 10, // Long Mode Active R/W + LME = 8, // Long Mode Enable R/W + SCE = 0, // System Call Extensions R/W +}; struct ControlRegister : std::bitset<64> { @@ -259,6 +270,10 @@ struct FlagRegister : std::bitset<64> } }; +struct FeatureRegister : std::bitset<64> +{ +}; + static uint32_t g_sessionId {0}; diff --git a/python/src/bochscpu_cpu.cpp b/python/src/bochscpu_cpu.cpp index b0357a8..a26df9e 100644 --- a/python/src/bochscpu_cpu.cpp +++ b/python/src/bochscpu_cpu.cpp @@ -77,6 +77,18 @@ bochscpu_cpu_module(nb::module_& base_module) .value("CF", BochsCPU::Cpu::FlagRegisterFlag::CF, "Carry Flag R/W") .export_values(); + nb::enum_(m, "FeatureRegisterFlag") + .value("TCE", BochsCPU::Cpu::FeatureRegisterFlag::TCE, "Translation Cache Extension R/W") + .value("FFXSR", BochsCPU::Cpu::FeatureRegisterFlag::FFXSR, "Fast FXSAVE/FXRSTOR R/W") + .value("LMSLE", BochsCPU::Cpu::FeatureRegisterFlag::LMSLE, "Long Mode Segment Limit Enable R/W") + .value("SVME", BochsCPU::Cpu::FeatureRegisterFlag::SVME, "Secure Virtual Machine Enable R/W") + .value("NXE", BochsCPU::Cpu::FeatureRegisterFlag::NXE, "No-Execute Enable R/W") + .value("LMA", BochsCPU::Cpu::FeatureRegisterFlag::LMA, "Long Mode Active R/W") + .value("LME", BochsCPU::Cpu::FeatureRegisterFlag::LME, "Long Mode Enable R/W") + .value("SCE", BochsCPU::Cpu::FeatureRegisterFlag::SCE, "System Call Extensions R/W") + .export_values(); + +#pragma region ControlRegister nb::class_(m, "ControlRegister") .def(nb::init<>()) .def_prop_rw( @@ -332,8 +344,9 @@ bochscpu_cpu_module(nb::module_& base_module) { return cr.to_ullong(); }); +#pragma endregion - +#pragma region FlagRegistrer nb::class_(m, "FlagRegister") .def(nb::init<>()) .def_prop_rw( @@ -559,6 +572,104 @@ bochscpu_cpu_module(nb::module_& base_module) { return fr.to_ullong(); }); +#pragma endregion + +#pragma region FeatureRegister + nb::class_(m, "FeatureRegister") + .def(nb::init<>()) + + .def_prop_rw( + "TCE", + [](BochsCPU::Cpu::FeatureRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FeatureRegisterFlag::TCE); + }, + [](BochsCPU::Cpu::FeatureRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FeatureRegisterFlag::TCE, onoff); + }, + "Translation Cache Extension R/W") + .def_prop_rw( + "FFXSR", + [](BochsCPU::Cpu::FeatureRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FeatureRegisterFlag::FFXSR); + }, + [](BochsCPU::Cpu::FeatureRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FeatureRegisterFlag::FFXSR, onoff); + }, + "Fast FXSAVE/FXRSTOR R/W") + .def_prop_rw( + "LMSLE", + [](BochsCPU::Cpu::FeatureRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FeatureRegisterFlag::LMSLE); + }, + [](BochsCPU::Cpu::FeatureRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FeatureRegisterFlag::LMSLE, onoff); + }, + "Long Mode Segment Limit Enable R/W") + .def_prop_rw( + "SVME", + [](BochsCPU::Cpu::FeatureRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FeatureRegisterFlag::SVME); + }, + [](BochsCPU::Cpu::FeatureRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FeatureRegisterFlag::SVME, onoff); + }, + "Secure Virtual Machine Enable R/W") + .def_prop_rw( + "NXE", + [](BochsCPU::Cpu::FeatureRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FeatureRegisterFlag::NXE); + }, + [](BochsCPU::Cpu::FeatureRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FeatureRegisterFlag::NXE, onoff); + }, + "No-Execute Enable R/W") + .def_prop_rw( + "LMA", + [](BochsCPU::Cpu::FeatureRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FeatureRegisterFlag::LMA); + }, + [](BochsCPU::Cpu::FeatureRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FeatureRegisterFlag::LMA, onoff); + }, + "Long Mode Active R/W") + .def_prop_rw( + "LME", + [](BochsCPU::Cpu::FeatureRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FeatureRegisterFlag::LME); + }, + [](BochsCPU::Cpu::FeatureRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FeatureRegisterFlag::LME, onoff); + }, + "Long Mode Enable R/W") + .def_prop_rw( + "SCE", + [](BochsCPU::Cpu::FeatureRegister& fr) + { + return fr.test((int)BochsCPU::Cpu::FeatureRegisterFlag::SCE); + }, + [](BochsCPU::Cpu::FeatureRegister& fr, bool onoff) + { + fr.set((int)BochsCPU::Cpu::FeatureRegisterFlag::SCE, onoff); + }, + "System Call Extensions R/W") + + + ; +#pragma endregion nb::class_(m, "cpu") .def_ro("id", &BochsCPU::Cpu::CPU::id) From 285d583cae4cb5f3820ba8e51f4243bc5a64fab4 Mon Sep 17 00:00:00 2001 From: hugsy Date: Sun, 20 Aug 2023 08:56:15 -0700 Subject: [PATCH 06/11] pyi signatures for efer and rflags --- python/stubs/bochscpu/cpu.pyi | 296 ++++++++++++++++++++++++++++++++++ 1 file changed, 296 insertions(+) diff --git a/python/stubs/bochscpu/cpu.pyi b/python/stubs/bochscpu/cpu.pyi index 7e25fea..4e510f6 100644 --- a/python/stubs/bochscpu/cpu.pyi +++ b/python/stubs/bochscpu/cpu.pyi @@ -4,6 +4,8 @@ import bochscpu.cpu class ControlRegister: """ ControlRegister class + @ref AMD Manual Vol 2 - 3-1 + @ref AMD Manual Vol 2 - 3-7 """ @property @@ -356,6 +358,300 @@ class ControlRegisterFlag(Flag): """ ... +class FlagRegisterFlag(Flag): + ID: FlagRegisterFlag + """ID Flag R/W""" + VIP: FlagRegisterFlag + """Virtual Interrupt Pending R/W""" + VIF: FlagRegisterFlag + """Virtual Interrupt Flag R/W""" + AC: FlagRegisterFlag + """Alignment Check R/W""" + VM: FlagRegisterFlag + """Virtual-8086 Mode R/W""" + RF: FlagRegisterFlag + """Resume Flag R/W""" + Reserved4: FlagRegisterFlag + """Read as Zero""" + NT: FlagRegisterFlag + """Nested Task R/W""" + IOPL2: FlagRegisterFlag + """IOPL I/O Privilege Level R/W""" + IOPL1: FlagRegisterFlag + """IOPL I/O Privilege Level R/W""" + OF: FlagRegisterFlag + """Overflow Flag R/W""" + DF: FlagRegisterFlag + """Direction Flag R/W""" + IF: FlagRegisterFlag + """Interrupt Flag R/W""" + TF: FlagRegisterFlag + """Trap Flag R/W""" + SF: FlagRegisterFlag + """Sign Flag R/W""" + ZF: FlagRegisterFlag + """Zero Flag R/W""" + Reserved3: FlagRegisterFlag + """Read as Zero""" + AF: FlagRegisterFlag + """Auxiliary Flag R/W""" + Reserved2: FlagRegisterFlag + """Read as Zero""" + PF: FlagRegisterFlag + """Parity Flag R/W""" + Reserved1: FlagRegisterFlag + """Read as One""" + CF: FlagRegisterFlag + """Carry Flag R/W""" + +class FlagRegister: + @property + def ID(self) -> bool: + """Get ID Flag R/W""" + ... + @ID.setter + def ID(self, value: bool) -> None: + """Set ID Flag R/W""" + ... + @property + def VIP(self) -> bool: + """Get Virtual Interrupt Pending R/W""" + ... + @VIP.setter + def VIP(self, value: bool) -> None: + """Set Virtual Interrupt Pending R/W""" + ... + @property + def VIF(self) -> bool: + """Get Virtual Interrupt Flag R/W""" + ... + @VIF.setter + def VIF(self, value: bool) -> None: + """Set Virtual Interrupt Flag R/W""" + ... + @property + def AC(self) -> bool: + """Get Alignment Check R/W""" + ... + @AC.setter + def AC(self, value: bool) -> None: + """Set Alignment Check R/W""" + ... + @property + def VM(self) -> bool: + """Get Virtual-8086 Mode R/W""" + ... + @VM.setter + def VM(self, value: bool) -> None: + """Set Virtual-8086 Mode R/W""" + ... + @property + def RF(self) -> bool: + """Get Resume Flag R/W""" + ... + @RF.setter + def RF(self, value: bool) -> None: + """Set Resume Flag R/W""" + ... + @property + def Reserved4(self) -> bool: + """Get Read as Zero""" + ... + @property + def NT(self) -> bool: + """Get Nested Task R/W""" + ... + @NT.setter + def NT(self, value: bool) -> None: + """Set Nested Task R/W""" + ... + @property + def IOPL2(self) -> bool: + """Get IOPL I/O Privilege Level R/W""" + ... + @IOPL2.setter + def IOPL2(self, value: bool) -> None: + """Set IOPL I/O Privilege Level R/W""" + ... + @property + def IOPL1(self) -> bool: + """Get IOPL I/O Privilege Level R/W""" + ... + @IOPL1.setter + def IOPL1(self, value: bool) -> None: + """Set IOPL I/O Privilege Level R/W""" + ... + @property + def OF(self) -> bool: + """Get Overflow Flag R/W""" + ... + @OF.setter + def OF(self, value: bool) -> None: + """Set Overflow Flag R/W""" + ... + @property + def DF(self) -> bool: + """Get Direction Flag R/W""" + ... + @DF.setter + def DF(self, value: bool) -> None: + """Set Direction Flag R/W""" + ... + @property + def IF(self) -> bool: + """Get Interrupt Flag R/W""" + ... + @IF.setter + def IF(self, value: bool) -> None: + """Set Interrupt Flag R/W""" + ... + @property + def TF(self) -> bool: + """Get Trap Flag R/W""" + ... + @TF.setter + def TF(self, value: bool) -> None: + """Set Trap Flag R/W""" + ... + @property + def SF(self) -> bool: + """Get Sign Flag R/W""" + ... + @SF.setter + def SF(self, value: bool) -> None: + """Set Sign Flag R/W""" + ... + @property + def ZF(self) -> bool: + """Get Zero Flag R/W""" + ... + @ZF.setter + def ZF(self, value: bool) -> None: + """Set Zero Flag R/W""" + ... + @property + def Reserved3(self) -> bool: + """Get Read as Zero""" + ... + @property + def AF(self) -> bool: + """Get Auxiliary Flag R/W""" + ... + @AF.setter + def AF(self, value: bool) -> None: + """Set Auxiliary Flag R/W""" + ... + @property + def Reserved2(self) -> bool: + """Get Read as Zero""" + ... + @property + def PF(self) -> bool: + """Get Parity Flag R/W""" + ... + @PF.setter + def PF(self, value: bool) -> None: + """Set Parity Flag R/W""" + ... + @property + def Reserved1(self) -> bool: + """Get Read as One""" + ... + @property + def CF(self) -> bool: + """Get Carry Flag R/W""" + ... + @CF.setter + def CF(self, value: bool) -> None: + """Set Carry Flag R/W""" + ... + def __int__(self) -> int: ... + +class FeatureRegisterFlag(Flag): + TCE: FeatureRegisterFlag + """Translation Cache Extension R/W""" + FFXSR: FeatureRegisterFlag + """Fast FXSAVE/FXRSTOR R/W""" + LMSLE: FeatureRegisterFlag + """Long Mode Segment Limit Enable R/W""" + SVME: FeatureRegisterFlag + """Secure Virtual Machine Enable R/W""" + NXE: FeatureRegisterFlag + """No-Execute Enable R/W""" + LMA: FeatureRegisterFlag + """Long Mode Active R/W""" + LME: FeatureRegisterFlag + """Long Mode Enable R/W""" + SCE: FeatureRegisterFlag + """System Call Extensions R/W""" + +class FeatureRegister: + @property + def TCE(self) -> bool: + """Get Translation Cache Extension R/W""" + ... + @TCE.setter + def TCE(self, value: bool) -> None: + """Set Translation Cache Extension R/W""" + ... + @property + def FFXSR(self) -> bool: + """Get Fast FXSAVE/FXRSTOR R/W""" + ... + @FFXSR.setter + def FFXSR(self, value: bool) -> None: + """Set Fast FXSAVE/FXRSTOR R/W""" + ... + @property + def LMSLE(self) -> bool: + """Get Long Mode Segment Limit Enable R/W""" + ... + @LMSLE.setter + def LMSLE(self, value: bool) -> None: + """Set Long Mode Segment Limit Enable R/W""" + ... + @property + def SVME(self) -> bool: + """Get Secure Virtual Machine Enable R/W""" + ... + @SVME.setter + def SVME(self, value: bool) -> None: + """Set Secure Virtual Machine Enable R/W""" + ... + @property + def NXE(self) -> bool: + """Get No-Execute Enable R/W""" + ... + @NXE.setter + def NXE(self, value: bool) -> None: + """Set No-Execute Enable R/W""" + ... + @property + def LMA(self) -> bool: + """Get Long Mode Active R/W""" + ... + @LMA.setter + def LMA(self, value: bool) -> None: + """Set Long Mode Active R/W""" + ... + @property + def LME(self) -> bool: + """Get Long Mode Enable R/W""" + ... + @LME.setter + def LME(self, value: bool) -> None: + """Set Long Mode Enable R/W""" + ... + @property + def SCE(self) -> bool: + """Get System Call Extensions R/W""" + ... + @SCE.setter + def SCE(self, value: bool) -> None: + """Set System Call Extensions R/W""" + ... + def __int__(self) -> int: ... + class cpu: def __init__(*args, **kwargs): """ From 6cc8de3c3fc664c5ba4a83d75c6ecf6e8f6655d8 Mon Sep 17 00:00:00 2001 From: hugsy Date: Sun, 20 Aug 2023 09:35:09 -0700 Subject: [PATCH 07/11] adjusting example to use reigster classes --- examples/fib.py | 13 +++++- python/src/bochscpu_cpu.cpp | 84 ++++++++++++++++++----------------- python/stubs/bochscpu/cpu.pyi | 20 +++------ 3 files changed, 63 insertions(+), 54 deletions(-) diff --git a/examples/fib.py b/examples/fib.py index 0089fe5..042413b 100644 --- a/examples/fib.py +++ b/examples/fib.py @@ -28,6 +28,7 @@ def dbg(x: str): def mmap(sz: int = PAGE_SIZE, perm: str = "rw"): + assert platform.system() != "Windows" PROT_READ = 0x1 PROT_WRITE = 0x2 PROT_EXEC = 0x4 @@ -190,6 +191,15 @@ def emulate(code: bytes): cr4 = bochscpu.cpu.ControlRegister() cr4.PAE = True # required for long mode + rflags = bochscpu.cpu.FlagRegister() + rflags.IOPL = 1 + + efer = bochscpu.cpu.FeatureRegister() + efer.NXE = True + efer.LMA = True + efer.LME = True + efer.SCE = True + # # Manually craft the guest virtual & physical memory layout into a pagetable # Once done bind the resulting GPAs it to bochs @@ -248,7 +258,8 @@ def emulate(code: bytes): state.cr0 = int(cr0) state.cr3 = pml4 state.cr4 = int(cr4) - state.efer = 0xD01 + state.efer = int(efer) + state.rflags = int(rflags) cs = bochscpu.Segment() cs.present = True cs.selector = 0x33 diff --git a/python/src/bochscpu_cpu.cpp b/python/src/bochscpu_cpu.cpp index a26df9e..2667d50 100644 --- a/python/src/bochscpu_cpu.cpp +++ b/python/src/bochscpu_cpu.cpp @@ -13,6 +13,7 @@ bochscpu_cpu_module(nb::module_& base_module) { auto m = base_module.def_submodule("cpu", "CPU module"); +#pragma region ControlRegister nb::enum_(m, "ControlRegisterFlag") // cr0 .value("PG", BochsCPU::Cpu::ControlRegisterFlag::PG, "Paging R/W") @@ -52,43 +53,6 @@ bochscpu_cpu_module(nb::module_& base_module) .value("VME", BochsCPU::Cpu::ControlRegisterFlag::VME, "Virtual-8086 Mode Extensions R/W") .export_values(); - nb::enum_(m, "FlagRegisterFlag") - .value("ID", BochsCPU::Cpu::FlagRegisterFlag::ID, "ID Flag R/W") - .value("VIP", BochsCPU::Cpu::FlagRegisterFlag::VIP, "Virtual Interrupt Pending R/W") - .value("VIF", BochsCPU::Cpu::FlagRegisterFlag::VIF, "Virtual Interrupt Flag R/W") - .value("AC", BochsCPU::Cpu::FlagRegisterFlag::AC, "Alignment Check R/W") - .value("VM", BochsCPU::Cpu::FlagRegisterFlag::VM, "Virtual-8086 Mode R/W") - .value("RF", BochsCPU::Cpu::FlagRegisterFlag::RF, "Resume Flag R/W") - .value("Reserved4", BochsCPU::Cpu::FlagRegisterFlag::Reserved4, "Read as Zero") - .value("NT", BochsCPU::Cpu::FlagRegisterFlag::NT, "Nested Task R/W") - .value("IOPL2", BochsCPU::Cpu::FlagRegisterFlag::IOPL2, "IOPL I/O Privilege Level R/W") - .value("IOPL1", BochsCPU::Cpu::FlagRegisterFlag::IOPL1, "IOPL I/O Privilege Level R/W") - .value("OF", BochsCPU::Cpu::FlagRegisterFlag::OF, "Overflow Flag R/W") - .value("DF", BochsCPU::Cpu::FlagRegisterFlag::DF, "Direction Flag R/W") - .value("IF", BochsCPU::Cpu::FlagRegisterFlag::IF, "Interrupt Flag R/W") - .value("TF", BochsCPU::Cpu::FlagRegisterFlag::TF, "Trap Flag R/W") - .value("SF", BochsCPU::Cpu::FlagRegisterFlag::SF, "Sign Flag R/W") - .value("ZF", BochsCPU::Cpu::FlagRegisterFlag::ZF, "Zero Flag R/W") - .value("Reserved3", BochsCPU::Cpu::FlagRegisterFlag::Reserved3, "Read as Zero") - .value("AF", BochsCPU::Cpu::FlagRegisterFlag::AF, "Auxiliary Flag R/W") - .value("Reserved2", BochsCPU::Cpu::FlagRegisterFlag::Reserved2, "Read as Zero") - .value("PF", BochsCPU::Cpu::FlagRegisterFlag::PF, "Parity Flag R/W") - .value("Reserved1", BochsCPU::Cpu::FlagRegisterFlag::Reserved1, "Read as One") - .value("CF", BochsCPU::Cpu::FlagRegisterFlag::CF, "Carry Flag R/W") - .export_values(); - - nb::enum_(m, "FeatureRegisterFlag") - .value("TCE", BochsCPU::Cpu::FeatureRegisterFlag::TCE, "Translation Cache Extension R/W") - .value("FFXSR", BochsCPU::Cpu::FeatureRegisterFlag::FFXSR, "Fast FXSAVE/FXRSTOR R/W") - .value("LMSLE", BochsCPU::Cpu::FeatureRegisterFlag::LMSLE, "Long Mode Segment Limit Enable R/W") - .value("SVME", BochsCPU::Cpu::FeatureRegisterFlag::SVME, "Secure Virtual Machine Enable R/W") - .value("NXE", BochsCPU::Cpu::FeatureRegisterFlag::NXE, "No-Execute Enable R/W") - .value("LMA", BochsCPU::Cpu::FeatureRegisterFlag::LMA, "Long Mode Active R/W") - .value("LME", BochsCPU::Cpu::FeatureRegisterFlag::LME, "Long Mode Enable R/W") - .value("SCE", BochsCPU::Cpu::FeatureRegisterFlag::SCE, "System Call Extensions R/W") - .export_values(); - -#pragma region ControlRegister nb::class_(m, "ControlRegister") .def(nb::init<>()) .def_prop_rw( @@ -347,6 +311,31 @@ bochscpu_cpu_module(nb::module_& base_module) #pragma endregion #pragma region FlagRegistrer + nb::enum_(m, "FlagRegisterFlag") + .value("ID", BochsCPU::Cpu::FlagRegisterFlag::ID, "ID Flag R/W") + .value("VIP", BochsCPU::Cpu::FlagRegisterFlag::VIP, "Virtual Interrupt Pending R/W") + .value("VIF", BochsCPU::Cpu::FlagRegisterFlag::VIF, "Virtual Interrupt Flag R/W") + .value("AC", BochsCPU::Cpu::FlagRegisterFlag::AC, "Alignment Check R/W") + .value("VM", BochsCPU::Cpu::FlagRegisterFlag::VM, "Virtual-8086 Mode R/W") + .value("RF", BochsCPU::Cpu::FlagRegisterFlag::RF, "Resume Flag R/W") + .value("Reserved4", BochsCPU::Cpu::FlagRegisterFlag::Reserved4, "Read as Zero") + .value("NT", BochsCPU::Cpu::FlagRegisterFlag::NT, "Nested Task R/W") + .value("IOPL2", BochsCPU::Cpu::FlagRegisterFlag::IOPL2, "IOPL I/O Privilege Level R/W") + .value("IOPL1", BochsCPU::Cpu::FlagRegisterFlag::IOPL1, "IOPL I/O Privilege Level R/W") + .value("OF", BochsCPU::Cpu::FlagRegisterFlag::OF, "Overflow Flag R/W") + .value("DF", BochsCPU::Cpu::FlagRegisterFlag::DF, "Direction Flag R/W") + .value("IF", BochsCPU::Cpu::FlagRegisterFlag::IF, "Interrupt Flag R/W") + .value("TF", BochsCPU::Cpu::FlagRegisterFlag::TF, "Trap Flag R/W") + .value("SF", BochsCPU::Cpu::FlagRegisterFlag::SF, "Sign Flag R/W") + .value("ZF", BochsCPU::Cpu::FlagRegisterFlag::ZF, "Zero Flag R/W") + .value("Reserved3", BochsCPU::Cpu::FlagRegisterFlag::Reserved3, "Read as Zero") + .value("AF", BochsCPU::Cpu::FlagRegisterFlag::AF, "Auxiliary Flag R/W") + .value("Reserved2", BochsCPU::Cpu::FlagRegisterFlag::Reserved2, "Read as Zero") + .value("PF", BochsCPU::Cpu::FlagRegisterFlag::PF, "Parity Flag R/W") + .value("Reserved1", BochsCPU::Cpu::FlagRegisterFlag::Reserved1, "Read as One") + .value("CF", BochsCPU::Cpu::FlagRegisterFlag::CF, "Carry Flag R/W") + .export_values(); + nb::class_(m, "FlagRegister") .def(nb::init<>()) .def_prop_rw( @@ -575,6 +564,18 @@ bochscpu_cpu_module(nb::module_& base_module) #pragma endregion #pragma region FeatureRegister + + nb::enum_(m, "FeatureRegisterFlag") + .value("TCE", BochsCPU::Cpu::FeatureRegisterFlag::TCE, "Translation Cache Extension R/W") + .value("FFXSR", BochsCPU::Cpu::FeatureRegisterFlag::FFXSR, "Fast FXSAVE/FXRSTOR R/W") + .value("LMSLE", BochsCPU::Cpu::FeatureRegisterFlag::LMSLE, "Long Mode Segment Limit Enable R/W") + .value("SVME", BochsCPU::Cpu::FeatureRegisterFlag::SVME, "Secure Virtual Machine Enable R/W") + .value("NXE", BochsCPU::Cpu::FeatureRegisterFlag::NXE, "No-Execute Enable R/W") + .value("LMA", BochsCPU::Cpu::FeatureRegisterFlag::LMA, "Long Mode Active R/W") + .value("LME", BochsCPU::Cpu::FeatureRegisterFlag::LME, "Long Mode Enable R/W") + .value("SCE", BochsCPU::Cpu::FeatureRegisterFlag::SCE, "System Call Extensions R/W") + .export_values(); + nb::class_(m, "FeatureRegister") .def(nb::init<>()) @@ -666,9 +667,12 @@ bochscpu_cpu_module(nb::module_& base_module) fr.set((int)BochsCPU::Cpu::FeatureRegisterFlag::SCE, onoff); }, "System Call Extensions R/W") - - - ; + .def( + "__int__", + [](BochsCPU::Cpu::FeatureRegister& fr) + { + return fr.to_ullong(); + }); #pragma endregion nb::class_(m, "cpu") diff --git a/python/stubs/bochscpu/cpu.pyi b/python/stubs/bochscpu/cpu.pyi index 4e510f6..2d3853b 100644 --- a/python/stubs/bochscpu/cpu.pyi +++ b/python/stubs/bochscpu/cpu.pyi @@ -4,8 +4,10 @@ import bochscpu.cpu class ControlRegister: """ ControlRegister class - @ref AMD Manual Vol 2 - 3-1 - @ref AMD Manual Vol 2 - 3-7 + @ref AMD Manual Vol 2 - 3-1 (CR0) + @ref AMD Manual Vol 2 - 3-7 (CR4) + @ref AMD Manual Vol 2 - 3-8 (RFLAGS) + @ref AMD Manual Vol 2 - 3-9 (EFER) """ @property @@ -466,19 +468,11 @@ class FlagRegister: """Set Nested Task R/W""" ... @property - def IOPL2(self) -> bool: + def IOPL(self) -> int: """Get IOPL I/O Privilege Level R/W""" ... - @IOPL2.setter - def IOPL2(self, value: bool) -> None: - """Set IOPL I/O Privilege Level R/W""" - ... - @property - def IOPL1(self) -> bool: - """Get IOPL I/O Privilege Level R/W""" - ... - @IOPL1.setter - def IOPL1(self, value: bool) -> None: + @IOPL.setter + def IOPL(self, value: int) -> None: """Set IOPL I/O Privilege Level R/W""" ... @property From 7b16e7f184deb205cfbf8f93da422af9c5e9d6bc Mon Sep 17 00:00:00 2001 From: hugsy Date: Sun, 20 Aug 2023 10:40:58 -0700 Subject: [PATCH 08/11] Moved stubs to the correct folder --- examples/fib.py | 13 ++++++++++--- python/CMakeLists.txt | 1 + .../{stubs/bochscpu => bochscpu-stubs}/__init__.pyi | 3 +++ python/{stubs/bochscpu => bochscpu-stubs}/cpu.pyi | 1 + .../{stubs/bochscpu => bochscpu-stubs}/memory.pyi | 4 ++-- 5 files changed, 17 insertions(+), 5 deletions(-) rename python/{stubs/bochscpu => bochscpu-stubs}/__init__.pyi (99%) rename python/{stubs/bochscpu => bochscpu-stubs}/cpu.pyi (99%) rename python/{stubs/bochscpu => bochscpu-stubs}/memory.pyi (91%) diff --git a/examples/fib.py b/examples/fib.py index 042413b..ee13cee 100644 --- a/examples/fib.py +++ b/examples/fib.py @@ -8,15 +8,20 @@ import keystone import bochscpu +import bochscpu.cpu +import bochscpu.memory DEBUG = True PAGE_SIZE = bochscpu.memory.PageSize() -@dataclasses.dataclass class Stats: insn_nb: int = 0 - mem_access: list[int] = dataclasses.field(default_factory=lambda: [0, 0, 0]) + mem_access: dict[bochscpu.memory.AccessType, int] = { + bochscpu.memory.AccessType.Read: 0, + bochscpu.memory.AccessType.Write: 0, + bochscpu.memory.AccessType.Execute: 0, + } stats = Stats() @@ -299,7 +304,9 @@ def emulate(code: bytes): f"vm stopped, execution: {stats.insn_nb} insns in {t2-t1}ns (~{int(stats.insn_nb // ((t2-t1)/1_000_000_000))}) insn/s" ) dbg( - f"mem accesses: read={stats.mem_access[0]} write={stats.mem_access[1]} execute={stats.mem_access[2]}" + f"mem accesses: read={stats.mem_access[bochscpu.memory.AccessType.Read]} " + f"write={stats.mem_access[bochscpu.memory.AccessType.Write]} " + f"execute={stats.mem_access[bochscpu.memory.AccessType.Execute]}" ) if stats.insn_nb < len(INSNS): diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 3e38bf7..ac748b2 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -34,6 +34,7 @@ else() endif() install(TARGETS bochscpu LIBRARY DESTINATION .) +install(DIRECTORY bochscpu-stubs DESTINATION .) if(MSVC) install(FILES $ DESTINATION . OPTIONAL) diff --git a/python/stubs/bochscpu/__init__.pyi b/python/bochscpu-stubs/__init__.pyi similarity index 99% rename from python/stubs/bochscpu/__init__.pyi rename to python/bochscpu-stubs/__init__.pyi index 4ff6031..75c593d 100644 --- a/python/stubs/bochscpu/__init__.pyi +++ b/python/bochscpu-stubs/__init__.pyi @@ -1,6 +1,7 @@ from typing import Any, Callable, Optional, overload from enum import Enum import bochscpu +import bochscpu.cpu class GlobalSegment: """ @@ -135,6 +136,8 @@ class Segment: Get/Set the Segment `selector` attribute """ ... + def __int__(self) -> int: + """Get the selector value as an integer""" class State: """ diff --git a/python/stubs/bochscpu/cpu.pyi b/python/bochscpu-stubs/cpu.pyi similarity index 99% rename from python/stubs/bochscpu/cpu.pyi rename to python/bochscpu-stubs/cpu.pyi index 2d3853b..0b2eb98 100644 --- a/python/stubs/bochscpu/cpu.pyi +++ b/python/bochscpu-stubs/cpu.pyi @@ -299,6 +299,7 @@ class ControlRegister: """ ... def __init__(self) -> None: ... + def __int__(self) -> int: ... class ControlRegisterFlag(Flag): """ diff --git a/python/stubs/bochscpu/memory.pyi b/python/bochscpu-stubs/memory.pyi similarity index 91% rename from python/stubs/bochscpu/memory.pyi rename to python/bochscpu-stubs/memory.pyi index 4f3b3fb..527c50e 100644 --- a/python/stubs/bochscpu/memory.pyi +++ b/python/bochscpu-stubs/memory.pyi @@ -42,7 +42,7 @@ def phy_read(gpa: int, size: int) -> list[int]: ... def phy_translate(gpa: int) -> int: ... -def phy_write(gpa: int, hva: list[int]) -> None: +def phy_write(gpa: int, hva: bytes) -> None: """ Write to GPA """ @@ -55,7 +55,7 @@ def virt_read(cr3: int, gva: int, sz: int) -> list[int]: ... def virt_translate(cr3: int, gva: int) -> int: ... -def virt_write(cr3: int, gva: int, hva: list[int]) -> bool: +def virt_write(cr3: int, gva: int, hva: bytes) -> bool: """ Write to GVA """ From 0d8dce76ac9d4b39a8f0447973a91d856b00134d Mon Sep 17 00:00:00 2001 From: hugsy Date: Sun, 20 Aug 2023 10:44:47 -0700 Subject: [PATCH 09/11] Added small comment about folder naming convention for stubs --- python/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index ac748b2..62a8e51 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -34,7 +34,7 @@ else() endif() install(TARGETS bochscpu LIBRARY DESTINATION .) -install(DIRECTORY bochscpu-stubs DESTINATION .) +install(DIRECTORY bochscpu-stubs DESTINATION .) # Folder name must be *-stubs, see PEP 561 if(MSVC) install(FILES $ DESTINATION . OPTIONAL) From f7d88ebdd8c14507195e4c2789bd04ffef8d4def Mon Sep 17 00:00:00 2001 From: hugsy Date: Sun, 20 Aug 2023 11:55:23 -0700 Subject: [PATCH 10/11] Add more types --- examples/fib.py | 13 ++++++--- python/bochscpu-stubs/cpu.pyi | 21 ++++++++++++++- python/inc/bochscpu.hpp | 51 ++++++++++++++++++++++++++++++----- python/src/bochscpu_cpu.cpp | 24 +++++++++++++++++ 4 files changed, 99 insertions(+), 10 deletions(-) diff --git a/examples/fib.py b/examples/fib.py index ee13cee..d5c1e57 100644 --- a/examples/fib.py +++ b/examples/fib.py @@ -147,8 +147,15 @@ def missing_page_cb(gpa): raise Exception(f"missing_page_cb({gpa=:#x})") -def exception_cb(sess: bochscpu.session, cpu_id: int, vector: int, error_code: int): - dbg(f"received exception({vector=:d}, {error_code=:d}) from cpu#{cpu_id}") +def exception_cb( + sess: bochscpu.session, + cpu_id: int, + vector: bochscpu.cpu.ExceptionType, + error_code: bochscpu.InstructionType, +): + match (vector, error_code): + case _: + dbg(f"cpu#{cpu_id} received exception({vector=:d}, {error_code=:d}) ") sess.stop() @@ -352,9 +359,9 @@ def emulate(code: bytes): hlt """ - cs = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_64) code, _ = ks.asm(fib) assert isinstance(code, list) code = bytearray(code) + cs = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_64) INSNS = [i for i in cs.disasm(code, 0)] emulate(code) diff --git a/python/bochscpu-stubs/cpu.pyi b/python/bochscpu-stubs/cpu.pyi index 0b2eb98..48a7010 100644 --- a/python/bochscpu-stubs/cpu.pyi +++ b/python/bochscpu-stubs/cpu.pyi @@ -1,4 +1,4 @@ -from enum import Flag +from enum import Flag, Enum import bochscpu.cpu class ControlRegister: @@ -647,6 +647,25 @@ class FeatureRegister: ... def __int__(self) -> int: ... +class ExceptionType(Enum): + DivideError: ExceptionType + Debug: ExceptionType + BreakPoint: ExceptionType + Overflow: ExceptionType + BoundRange: ExceptionType + InvalidOpcode: ExceptionType + NonMaskable: ExceptionType + DoubleFfault: ExceptionType + InvalidTss: ExceptionType + NotPresentSegment: ExceptionType + Stack: ExceptionType + GeneralProtection: ExceptionType + PageFault: ExceptionType + FloatingPoint: ExceptionType + AlignmentCheck: ExceptionType + MachineCheck: ExceptionType + ControlProtection: ExceptionType + class cpu: def __init__(*args, **kwargs): """ diff --git a/python/inc/bochscpu.hpp b/python/inc/bochscpu.hpp index deec650..fb3aea1 100644 --- a/python/inc/bochscpu.hpp +++ b/python/inc/bochscpu.hpp @@ -55,8 +55,34 @@ namespace BochsCPU { +/// +/// @brief Src https://github.com/lubomyr/bochs/blob/8e0b9abcd81cd24d4d9c68f7fdef2f53bc180d33/cpu/cpu.h#L306 +/// +/// +enum class BochsException : uint32_t +{ + BX_DE_EXCEPTION = 0, // Divide Error (fault) + BX_DB_EXCEPTION = 1, // Debug (fault/trap) + BX_BP_EXCEPTION = 3, // Breakpoint (trap) + BX_OF_EXCEPTION = 4, // Overflow (trap) + BX_BR_EXCEPTION = 5, // BOUND (fault) + BX_UD_EXCEPTION = 6, + BX_NM_EXCEPTION = 7, + BX_DF_EXCEPTION = 8, + BX_TS_EXCEPTION = 10, + BX_NP_EXCEPTION = 11, + BX_SS_EXCEPTION = 12, + BX_GP_EXCEPTION = 13, + BX_PF_EXCEPTION = 14, + BX_MF_EXCEPTION = 16, + BX_AC_EXCEPTION = 17, + BX_MC_EXCEPTION = 18, + BX_XM_EXCEPTION = 19, + BX_VE_EXCEPTION = 20, + BX_CP_EXCEPTION = 21 // Control Protection (fault) +}; -enum class InstructionType +enum class InstructionType : uint32_t { BX_INSTR_IS_JMP = BX_INSTR_IS_JMP, BOCHSCPU_INSTR_IS_JMP_INDIRECT = BOCHSCPU_INSTR_IS_JMP_INDIRECT, @@ -72,7 +98,7 @@ enum class InstructionType }; -enum class HookType +enum class HookType : uint32_t { BOCHSCPU_HOOK_MEM_READ = BOCHSCPU_HOOK_MEM_READ, BOCHSCPU_HOOK_MEM_WRITE = BOCHSCPU_HOOK_MEM_WRITE, @@ -96,6 +122,19 @@ enum class OpcodeOperationType BOCHSCPU_OPCODE_INSERTED = BOCHSCPU_OPCODE_INSERTED, }; +/// +/// @brief https://github.com/lubomyr/bochs/blob/8e0b9abcd81cd24d4d9c68f7fdef2f53bc180d33/cpu/cpu.h#L336 +/// +/// +enum class BochsCpuMode : uint32_t +{ + BX_MODE_IA32_REAL = 0, // CR0.PE=0 | + BX_MODE_IA32_V8086 = 1, // CR0.PE=1, EFLAGS.VM=1 | EFER.LMA=0 + BX_MODE_IA32_PROTECTED = 2, // CR0.PE=1, EFLAGS.VM=0 | + BX_MODE_LONG_COMPAT = 3, // EFER.LMA = 1, CR0.PE=1, CS.L=0 + BX_MODE_LONG_64 = 4 // EFER.LMA = 1, CR0.PE=1, CS.L=1 +}; + namespace Callbacks { @@ -302,11 +341,11 @@ struct CPU namespace Memory { -enum class Access : int +enum class Access : uint32_t { - Read = 0, - Write = 1, - Execute = 2, + Read = BochsCPU::HookType::BOCHSCPU_HOOK_MEM_READ, + Write = BochsCPU::HookType::BOCHSCPU_HOOK_MEM_WRITE, + Execute = BochsCPU::HookType::BOCHSCPU_HOOK_MEM_EXECUTE, }; uintptr_t diff --git a/python/src/bochscpu_cpu.cpp b/python/src/bochscpu_cpu.cpp index 2667d50..0549b42 100644 --- a/python/src/bochscpu_cpu.cpp +++ b/python/src/bochscpu_cpu.cpp @@ -675,6 +675,30 @@ bochscpu_cpu_module(nb::module_& base_module) }); #pragma endregion + /// + /// @brief AMD Manual Vol 2 - 8.1 + /// + /// + nb::enum_(m, "ExceptionType", "CPU Exceptions") + .value("DivideError", BochsCPU::BochsException::BX_DE_EXCEPTION) + .value("Debug", BochsCPU::BochsException::BX_DB_EXCEPTION) + .value("BreakPoint", BochsCPU::BochsException::BX_BP_EXCEPTION) + .value("Overflow", BochsCPU::BochsException::BX_OF_EXCEPTION) + .value("BoundRange", BochsCPU::BochsException::BX_BR_EXCEPTION) + .value("InvalidOpcode", BochsCPU::BochsException::BX_UD_EXCEPTION) + .value("NonMaskable", BochsCPU::BochsException::BX_NM_EXCEPTION) + .value("DoubleFfault", BochsCPU::BochsException::BX_DF_EXCEPTION) + .value("InvalidTss", BochsCPU::BochsException::BX_TS_EXCEPTION) + .value("NotPresentSegment", BochsCPU::BochsException::BX_NP_EXCEPTION) + .value("Stack", BochsCPU::BochsException::BX_SS_EXCEPTION) + .value("GeneralProtection", BochsCPU::BochsException::BX_GP_EXCEPTION) + .value("PageFault", BochsCPU::BochsException::BX_PF_EXCEPTION) + .value("FloatingPoint", BochsCPU::BochsException::BX_MF_EXCEPTION) + .value("AlignmentCheck", BochsCPU::BochsException::BX_AC_EXCEPTION) + .value("MachineCheck", BochsCPU::BochsException::BX_MC_EXCEPTION) + .value("ControlProtection", BochsCPU::BochsException::BX_CP_EXCEPTION) + .export_values(); + nb::class_(m, "cpu") .def_ro("id", &BochsCPU::Cpu::CPU::id) From 0ae4c77b0ce2b29c096e96f9767a9f99344409d5 Mon Sep 17 00:00:00 2001 From: hugsy Date: Sun, 20 Aug 2023 12:05:39 -0700 Subject: [PATCH 11/11] Linux fix --- python/inc/bochscpu.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/inc/bochscpu.hpp b/python/inc/bochscpu.hpp index fb3aea1..800c398 100644 --- a/python/inc/bochscpu.hpp +++ b/python/inc/bochscpu.hpp @@ -343,9 +343,9 @@ namespace Memory enum class Access : uint32_t { - Read = BochsCPU::HookType::BOCHSCPU_HOOK_MEM_READ, - Write = BochsCPU::HookType::BOCHSCPU_HOOK_MEM_WRITE, - Execute = BochsCPU::HookType::BOCHSCPU_HOOK_MEM_EXECUTE, + Read = (uint32_t)BochsCPU::HookType::BOCHSCPU_HOOK_MEM_READ, + Write = (uint32_t)BochsCPU::HookType::BOCHSCPU_HOOK_MEM_WRITE, + Execute = (uint32_t)BochsCPU::HookType::BOCHSCPU_HOOK_MEM_EXECUTE, }; uintptr_t