Logging.c and UnloadDll.c compile and link into HyperDbg.ko, along with
the two components that were waiting on the logging layer (BinarySearch,
OptimizationsExamples).
- new PlatformStr.{h,c}: PlatformVsnprintf/Sprintf/Strnlen replace
vsprintf_s/sprintf_s/strnlen_s; PlatformSprintf moved here out of
PlatformMem so both spellings return -1 on truncation
- BasicTypes.h: IRP/IO_STACK_LOCATION/IO_STATUS_BLOCK/UNICODE_STRING
grow the members shared code touches, plus the NT status and access
constants the notify path needs
- Environment.h: RTL_NUMBER_OF, _Analysis_assume_, ASSERT -> WARN_ON
- PlatformEvent: ExEventObjectType placeholder token
- HyperLogCallback.c stays out of the module: it defines the same
LogCallback* entry points as Logging.c (it is the per-DLL forwarding
shim on Windows), so in one link unit it is a duplicate symbol
Route Spinlock.c's three MSVC intrinsics through the platform
intrinsics layer instead of the Windows builtins:
_mm_pause -> CpuPause (already existed)
_interlockedbittestandset -> CpuInterlockedBitTestAndSet (new)
InterlockedCompareExchange-> CpuInterlockedCompareExchange (new, 32-bit)
Add the two new Cpu* wrappers to the kernel PlatformIntrinsics
{.h,.c} with win + linux arms (Linux uses __atomic_* builtins,
mirroring the existing 64-bit CAS), keeping the Cpu* wrappers the
single intrinsic boundary.
Filled in the stubs for the windows functions:
KeQueryActiveProcessorCount(0) and KeGetCurrentProcessorNumberEx(NULL).
KeQueryActiveProcessorCount(0) maps one to one to num_online_cpus()
KeGetCurrentProcessorNumberEx(NULL) maps to raw_smp_processor_id(),
however this can also be smp_processor_id(), we have to decide based on
preemption, the latter checks for preemption and throws a warning if it
is executed in preemptible code. (I dont know the kernel code well
enough so this may need some discussion)
When the debugger drops the serial link uncleanly mid-frame (no CLOSE_AND_UNLOAD packet), SerialConnectionRecvBuffer overflowed without an end-of-buffer marker and returned FALSE into the KD dispatch loop retry. The loop re-entered the same desynced stream, so it overflowed again at once and flooded 'buffer exceeds the buffer limitation' (and could wedge the KD driver on the next reconnect). Discard bytes to the next end-of-buffer marker to re-align, start a fresh frame, and log once per desync episode with LogWarning. Framing and protocol are unchanged.
Refs #661
- Add ucpuid command to commands.h and help.h
- Add IOCTL definitions for CPUID
- Use macros for CPUID leaf decoding
- Update Connection.h with new packet types
In Debugger Mode, breaking the debuggee and then reading registers (e.g. the
'r' command) could bugcheck the debuggee with DRIVER_IRQL_NOT_LESS_OR_EQUAL
(0xD1) at IRQL 0xff.
Root cause: DebuggerCommandReadRegisters() copies GUEST_REGS from
DbgState->Regs, but the per-core DbgState->Regs is only populated on the
event-triggered halt paths. A core halted via a manual break
(DEBUGGER_VMCALL_VM_EXIT_HALT_SYSTEM) or via the NMI broadcast (KdHandleNmi)
never had DbgState->Regs set, so it was NULL and the GUEST_REGS memcpy
dereferenced address 0.
Fix:
- Add VmFuncGetGuestRegs(CoreId) returning g_GuestState[CoreId].Regs (the
guest GP registers saved on the last vm-exit).
- Populate DbgState->Regs from it on the two manual-halt entry points
(DEBUGGER_VMCALL_VM_EXIT_HALT_SYSTEM and KdHandleNmi) so register reads on a
manually-halted core return the correct values.
- Add a defensive NULL check in DebuggerCommandReadRegisters().