mirror of
https://dev.lirent.ru/Vatrog/vm-introspection-engine.git
synced 2026-07-09 00:46:36 +03:00
Add readable operand decode and register def-use analysis
insndec.h: insn_decode() decodes one instruction into a readable form - concrete registers as canonical roots (al/ah/ax/eax/rax -> one root), memory base/index/scale/disp, immediate values, operand sizes, per-operand read/write, and implicit operands/effects (rsp on push/pop, rdx:rax on mul/div, FLAGS). It is ABI-agnostic: a call reports only its architectural effects. codetrace.h: func_usedef(fn, abi, ...) computes per-instruction register use/def over a function view (reusing cfg_blocks), splitting writes into full-kill / partial / conditional so a reaching-definitions pass can be built on top. With TRACE_ABI_WIN64 it marks the Win64 caller-saved set (rax,rcx,rdx,r8-r11,xmm0-5,flags) clobbered at each call site; the clobber table is confined to codetrace.c and the generic layer stays OS-agnostic (TRACE_ABI_NONE keeps the conservative behaviour). Both ride the existing optional disassembler seam (a second insn_decode_full is added to semsig_backend.h; sem_insn and semsig_hash are untouched), gated behind VMIE_HAVE_DISASM; OFF builds a stub. Adds the vmie_win32_func_usedef wrapper. No new build option - the feature shares VMIE_DISASM with semsig.
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
#include "memmodel.h" /* vmie_mem, vregion/VR_*, task/range, gva_read/write/ptr/regions/sweep */
|
||||
#include "sigscan.h" /* mem_view_t, sig_pattern_t */
|
||||
#include "scan.h" /* scan_type, scan_ptr_path, generic scan surface */
|
||||
#include "codetrace.h" /* insn_usedef, trace_abi (register def-use surface) */
|
||||
|
||||
/* Opaque introspection context. Completed in src/engine/win32/engine-win32.h;
|
||||
* callers only ever hold a pointer. Created by vmie_win32_open(), populated by
|
||||
@@ -492,6 +493,40 @@ int vmie_win32_func_imports(vmie_win32* v, uint64_t cr3, uint64_t module_base,
|
||||
uint64_t vmie_win32_func_semsig(vmie_win32* v, uint64_t cr3,
|
||||
uint64_t module_base, uint32_t func_rva);
|
||||
|
||||
/* Register def-use of ONE function, addressed by its func_rva (a .pdata function
|
||||
* start, as from vmie_win32_functions or an export). The win32 convenience entry
|
||||
* point over the generic func_usedef (codetrace.h): it locates the function
|
||||
* extent from .pdata (like vmie_win32_func_semsig), gathers its body with
|
||||
* gva_read, builds a SECTION_LOCAL mem_view_t, and DELEGATES to func_usedef -
|
||||
* PASSING TRACE_ABI_WIN64, because choosing the Win64 calling convention is the
|
||||
* OS-specific decision that belongs in this layer (which already owns .pdata /
|
||||
* cr3 / module_base). It does NOT reimplement the analysis or apply the volatile
|
||||
* clobber itself (func_usedef does), and pulls in no disassembler backend (the
|
||||
* feature is inherited transitively via the same VMIE_HAVE_DISASM as the generic).
|
||||
*
|
||||
* v - engine handle.
|
||||
* cr3 - the process address space the module is mapped in.
|
||||
* module_base - image base VA (its PE headers must be resident).
|
||||
* func_rva - function start RVA (must match a .pdata function start).
|
||||
* out, max - caller array receiving up to `max` per-instruction insn_usedef
|
||||
* records in ascending function-local offset order (NULL to count).
|
||||
*
|
||||
* Returns the TOTAL instruction count, 0 if the function is empty, or -1 on any
|
||||
* of: func_rva is not a known function start, the body is unreadable (paged out),
|
||||
* a decode desync, or a build with no disassembler backend (VMIE_HAVE_DISASM==0).
|
||||
* The off field of each record is a function-local byte offset (SECTION_LOCAL).
|
||||
*
|
||||
* The Win64 volatile clobber applied at call sites - and its honest limits (only
|
||||
* the standard Win64 convention; not __vectorcall/custom; the return value is not
|
||||
* a separate def) - are documented at the clobber table in codetrace.c.
|
||||
*
|
||||
* Example - registers each instruction of a function kills:
|
||||
* insn_usedef ud[512];
|
||||
* int n = vmie_win32_func_usedef(v, pr->cr3, m.base, fn_rva, ud, 512);
|
||||
* for (int i = 0; i < n && i < 512; i++) ... inspect ud[i].def ... */
|
||||
int vmie_win32_func_usedef(vmie_win32* v, uint64_t cr3, uint64_t module_base,
|
||||
uint32_t func_rva, insn_usedef* out, int max);
|
||||
|
||||
/* Devirtualization (C++ vtables) needs NO dedicated symbol - it is a
|
||||
* COMPOSITION of primitives the engine already exposes:
|
||||
* - a vtable at `vtable_va` is an array of code pointers, so its METHODS are
|
||||
|
||||
Reference in New Issue
Block a user