mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-08-25 00:15:00 +00:00
commit
b57b886cb3
18 changed files with 758 additions and 285 deletions
|
|
@ -332,11 +332,12 @@ CommandTestQueryPreAllocPoolsState()
|
|||
|
||||
/**
|
||||
* @brief test command for setting target tasks to halted cores
|
||||
* @param Synchronous
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
CommandTestSetTargetTaskToHaltedCores()
|
||||
CommandTestSetTargetTaskToHaltedCores(BOOLEAN Synchronous)
|
||||
{
|
||||
if (!g_IsSerialConnectedToRemoteDebuggee)
|
||||
{
|
||||
|
|
@ -348,7 +349,29 @@ CommandTestSetTargetTaskToHaltedCores()
|
|||
//
|
||||
// Send the target tasks to the halted cores
|
||||
//
|
||||
KdSendTestQueryPacketToDebuggee(TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES);
|
||||
KdSendTestQueryPacketToDebuggee(Synchronous ? TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_SYNCHRONOUS : TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_ASYNCHRONOUS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief test command for setting target task to the specified core
|
||||
* @param CoreNumber
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
CommandTestSetTargetTaskToTargetCore(UINT32 CoreNumber)
|
||||
{
|
||||
if (!g_IsSerialConnectedToRemoteDebuggee)
|
||||
{
|
||||
ShowMessages("err, query state of the debuggee is only possible when you connected "
|
||||
"in debugger mode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Send the target task to the target halted core
|
||||
//
|
||||
KdSendTestQueryPacketWithContextToDebuggee(TEST_SETTING_TARGET_TASKS_ON_TARGET_HALTED_CORES, (UINT64)CoreNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -389,6 +412,8 @@ CommandTestSetBreakpointState(BOOLEAN State)
|
|||
VOID
|
||||
CommandTest(vector<string> SplittedCommand, string Command)
|
||||
{
|
||||
UINT64 Context = NULL;
|
||||
|
||||
if (SplittedCommand.size() == 1)
|
||||
{
|
||||
//
|
||||
|
|
@ -417,12 +442,32 @@ CommandTest(vector<string> SplittedCommand, string Command)
|
|||
//
|
||||
CommandTestQueryPreAllocPoolsState();
|
||||
}
|
||||
else if (SplittedCommand.size() == 2 && !SplittedCommand.at(1).compare("task"))
|
||||
else if (SplittedCommand.size() == 2 && !SplittedCommand.at(1).compare("sync-task"))
|
||||
{
|
||||
//
|
||||
// Send target task to the halted cores in debugger mode
|
||||
// Send target task to the halted cores in debugger mode (synchronous)
|
||||
//
|
||||
CommandTestSetTargetTaskToHaltedCores();
|
||||
CommandTestSetTargetTaskToHaltedCores(TRUE);
|
||||
}
|
||||
else if (SplittedCommand.size() == 2 && !SplittedCommand.at(1).compare("async-task"))
|
||||
{
|
||||
//
|
||||
// Send target task to the halted cores in debugger mode (asynchronous)
|
||||
//
|
||||
CommandTestSetTargetTaskToHaltedCores(FALSE);
|
||||
}
|
||||
else if (SplittedCommand.size() == 3 && !SplittedCommand.at(1).compare("target-core-task"))
|
||||
{
|
||||
if (!ConvertStringToUInt64(SplittedCommand.at(2), &Context))
|
||||
{
|
||||
ShowMessages("err, you should enter a valid hex number as the core id\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Send target task to the specific halted core in debugger mode
|
||||
//
|
||||
CommandTestSetTargetTaskToTargetCore((UINT32)Context);
|
||||
}
|
||||
else if (SplittedCommand.size() == 3 && !SplittedCommand.at(1).compare("breakpoint"))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -391,6 +391,13 @@ ShowErrorMessage(UINT32 Error)
|
|||
Error);
|
||||
break;
|
||||
|
||||
case DEBUGGER_ERROR_PROCESS_ID_CANNOT_BE_SPECIFIED_WHILE_APPLYING_EVENT_FROM_VMX_ROOT_MODE:
|
||||
ShowMessages("err, you cannot specify process id while the debugger is paused in the debugger mode. "
|
||||
"You can use the '.process' or the '.thread' command to switch to the target process's "
|
||||
"memory layout (%x)\n",
|
||||
Error);
|
||||
break;
|
||||
|
||||
default:
|
||||
ShowMessages("err, error not found (%x)\n",
|
||||
Error);
|
||||
|
|
|
|||
|
|
@ -417,6 +417,7 @@ KdSendCallStackPacketToDebuggee(UINT64 BaseAddress,
|
|||
* @brief Send a test query request to the debuggee
|
||||
*
|
||||
* @param Type
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
|
|
@ -446,6 +447,42 @@ KdSendTestQueryPacketToDebuggee(DEBUGGER_TEST_QUERY_STATE Type)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send a test query request to the debuggee with the specified context
|
||||
*
|
||||
* @param Type
|
||||
* @param Context
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
KdSendTestQueryPacketWithContextToDebuggee(DEBUGGER_TEST_QUERY_STATE Type, UINT64 Context)
|
||||
{
|
||||
DEBUGGER_DEBUGGER_TEST_QUERY_BUFFER TestQueryPacket = {0};
|
||||
|
||||
TestQueryPacket.RequestType = Type;
|
||||
TestQueryPacket.Context = Context;
|
||||
|
||||
//
|
||||
// Send 'test query' command as query packet
|
||||
//
|
||||
if (!KdCommandPacketAndBufferToDebuggee(
|
||||
DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_TEST_QUERY,
|
||||
(CHAR *)&TestQueryPacket,
|
||||
sizeof(DEBUGGER_DEBUGGER_TEST_QUERY_BUFFER)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Wait until the result of test query is received
|
||||
//
|
||||
DbgWaitForKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_TEST_QUERY);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send symbol reload packet to the debuggee
|
||||
*
|
||||
|
|
|
|||
|
|
@ -121,6 +121,9 @@ KdSendCallStackPacketToDebuggee(UINT64 BaseAddress,
|
|||
BOOLEAN
|
||||
KdSendTestQueryPacketToDebuggee(DEBUGGER_TEST_QUERY_STATE Type);
|
||||
|
||||
BOOLEAN
|
||||
KdSendTestQueryPacketWithContextToDebuggee(DEBUGGER_TEST_QUERY_STATE Type, UINT64 Context);
|
||||
|
||||
BOOLEAN
|
||||
KdSendSymbolReloadPacketToDebuggee(UINT32 ProcessId);
|
||||
|
||||
|
|
|
|||
|
|
@ -243,3 +243,27 @@ CommonKillProcess(UINT32 ProcessId, PROCESS_KILL_METHODS KillingMethod)
|
|||
//
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Validate core number
|
||||
* @param CoreNumber
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
_Use_decl_annotations_
|
||||
BOOLEAN
|
||||
CommonValidateCoreNumber(UINT32 CoreNumber)
|
||||
{
|
||||
ULONG CoreCount;
|
||||
|
||||
CoreCount = KeQueryActiveProcessorCount(0);
|
||||
|
||||
if (CoreNumber >= CoreCount)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -835,7 +835,6 @@ BOOLEAN
|
|||
BreakpointAddNew(PDEBUGGEE_BP_PACKET BpDescriptorArg)
|
||||
{
|
||||
PDEBUGGEE_BP_DESCRIPTOR BreakpointDescriptor = NULL;
|
||||
UINT32 ProcessorCount;
|
||||
CR3_TYPE GuestCr3;
|
||||
BOOLEAN IsAddress32Bit = FALSE;
|
||||
|
||||
|
|
@ -860,10 +859,8 @@ BreakpointAddNew(PDEBUGGEE_BP_PACKET BpDescriptorArg)
|
|||
//
|
||||
// Check if the core number is not invalid
|
||||
//
|
||||
ProcessorCount = KeQueryActiveProcessorCount(0);
|
||||
|
||||
if (BpDescriptorArg->Core != DEBUGGEE_BP_APPLY_TO_ALL_CORES &&
|
||||
BpDescriptorArg->Core >= ProcessorCount)
|
||||
!CommonValidateCoreNumber(BpDescriptorArg->Core))
|
||||
{
|
||||
//
|
||||
// Core is invalid (Set the error)
|
||||
|
|
|
|||
|
|
@ -2105,33 +2105,24 @@ DebuggerRemoveEvent(UINT64 Tag)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Routine for validating and parsing events
|
||||
* that came from user-mode
|
||||
* @brief validating events
|
||||
*
|
||||
* @param EventDetails The structure that describes event that came
|
||||
* from the user-mode
|
||||
* from the user-mode or VMX-root mode
|
||||
* @param BufferLength Length of the buffer
|
||||
* @param ResultsToReturnUsermode Result buffer that should be returned to
|
||||
* @param ResultsToReturn Result buffer that should be returned to
|
||||
* the user-mode
|
||||
* @return BOOLEAN TRUE if the event was valid an regisered without error,
|
||||
* otherwise returns FALSE
|
||||
* @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL
|
||||
*
|
||||
* @return BOOLEAN TRUE if the event was valid otherwise returns FALSE
|
||||
*/
|
||||
BOOLEAN
|
||||
DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT32 BufferLength, PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturnUsermode)
|
||||
DebuggerValidateEvent(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails,
|
||||
UINT32 BufferLength,
|
||||
PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturn,
|
||||
BOOLEAN InputFromVmxRoot)
|
||||
{
|
||||
PDEBUGGER_EVENT Event;
|
||||
UINT64 PagesBytes;
|
||||
UINT32 TempPid;
|
||||
UINT32 ProcessorCount;
|
||||
BOOLEAN ResultOfApplyingEvent = FALSE;
|
||||
|
||||
ProcessorCount = KeQueryActiveProcessorCount(0);
|
||||
|
||||
//
|
||||
// ----------------------------------------------------------------------------------
|
||||
// *** Validating the Event's parameters ***
|
||||
// ----------------------------------------------------------------------------------
|
||||
//
|
||||
UINT32 TempPid;
|
||||
|
||||
//
|
||||
// Check whether the event mode (calling stage) to see whether
|
||||
|
|
@ -2143,8 +2134,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
|
|||
EventDetails->EventStage == VMM_CALLBACK_CALLING_STAGE_ALL_EVENT_EMULATION) &&
|
||||
EventDetails->EnableShortCircuiting == TRUE)
|
||||
{
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DEBUGGER_ERROR_USING_SHORT_CIRCUITING_EVENT_WITH_POST_EVENT_MODE_IS_FORBIDDEDN;
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_USING_SHORT_CIRCUITING_EVENT_WITH_POST_EVENT_MODE_IS_FORBIDDEDN;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -2157,14 +2148,14 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
|
|||
//
|
||||
// Check if the core number is not invalid
|
||||
//
|
||||
if (EventDetails->CoreId >= ProcessorCount)
|
||||
if (!CommonValidateCoreNumber(EventDetails->CoreId))
|
||||
{
|
||||
//
|
||||
// CoreId is invalid (Set the error)
|
||||
//
|
||||
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DEBUGGER_ERROR_INVALID_CORE_ID;
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_CORE_ID;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -2176,13 +2167,19 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
|
|||
if (EventDetails->ProcessId != DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES && EventDetails->ProcessId != 0)
|
||||
{
|
||||
//
|
||||
// The used specified a special pid, let's check if it's valid or not
|
||||
// Here we prefer not to validate the process id, if it's applied from VMX-root mode
|
||||
//
|
||||
if (!CommonIsProcessExist(EventDetails->ProcessId))
|
||||
if (!InputFromVmxRoot)
|
||||
{
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DEBUGGER_ERROR_INVALID_PROCESS_ID;
|
||||
return FALSE;
|
||||
//
|
||||
// The used specified a special pid, let's check if it's valid or not
|
||||
//
|
||||
if (!CommonIsProcessExist(EventDetails->ProcessId))
|
||||
{
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_PROCESS_ID;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2199,8 +2196,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
|
|||
// more than 32 indexes we should use pin-based external interrupt
|
||||
// exiting which is completely different
|
||||
//
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DEBUGGER_ERROR_EXCEPTION_INDEX_EXCEED_FIRST_32_ENTRIES;
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_EXCEPTION_INDEX_EXCEED_FIRST_32_ENTRIES;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -2215,8 +2212,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
|
|||
// The IDT Entry is either invalid or is not in the range
|
||||
// of the pin-based external interrupt exiting controls
|
||||
//
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DEBUGGER_ERROR_INTERRUPT_INDEX_IS_NOT_VALID;
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_INTERRUPT_INDEX_IS_NOT_VALID;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -2232,8 +2229,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
|
|||
//
|
||||
// The execution mode is not correctly applied
|
||||
//
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DEBUGGER_ERROR_MODE_EXECUTION_IS_INVALID;
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_MODE_EXECUTION_IS_INVALID;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -2243,21 +2240,55 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
|
|||
// First check if the address are valid
|
||||
//
|
||||
TempPid = EventDetails->ProcessId;
|
||||
|
||||
if (TempPid == DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES)
|
||||
{
|
||||
TempPid = PsGetCurrentProcessId();
|
||||
}
|
||||
|
||||
if (VirtualAddressToPhysicalAddressByProcessId(EventDetails->OptionalParam1, TempPid) == NULL)
|
||||
//
|
||||
// Check if input is coming from VMX-root or not
|
||||
// If it's coming from VMX-root, then as switching
|
||||
// to another process is not possible, we'll return
|
||||
// an error
|
||||
//
|
||||
if (InputFromVmxRoot && TempPid != PsGetCurrentProcessId())
|
||||
{
|
||||
//
|
||||
// Address is invalid (Set the error)
|
||||
//
|
||||
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DEBUGGER_ERROR_INVALID_ADDRESS;
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_PROCESS_ID_CANNOT_BE_SPECIFIED_WHILE_APPLYING_EVENT_FROM_VMX_ROOT_MODE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Check whether address is valid or not based on whether the event needs
|
||||
// to be applied directly from VMX-root mode or not
|
||||
//
|
||||
if (InputFromVmxRoot)
|
||||
{
|
||||
if (VirtualAddressToPhysicalAddressOnTargetProcess(EventDetails->OptionalParam1) == NULL)
|
||||
{
|
||||
//
|
||||
// Address is invalid (Set the error)
|
||||
//
|
||||
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (VirtualAddressToPhysicalAddressByProcessId(EventDetails->OptionalParam1, TempPid) == NULL)
|
||||
{
|
||||
//
|
||||
// Address is invalid (Set the error)
|
||||
//
|
||||
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (EventDetails->EventType == HIDDEN_HOOK_READ_AND_WRITE_AND_EXECUTE ||
|
||||
EventDetails->EventType == HIDDEN_HOOK_READ_AND_WRITE ||
|
||||
|
|
@ -2276,92 +2307,90 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
|
|||
TempPid = PsGetCurrentProcessId();
|
||||
}
|
||||
|
||||
if (VirtualAddressToPhysicalAddressByProcessId(EventDetails->OptionalParam1, TempPid) == NULL || VirtualAddressToPhysicalAddressByProcessId(EventDetails->OptionalParam2, TempPid) == NULL)
|
||||
//
|
||||
// Check if input is coming from VMX-root or not
|
||||
// If it's coming from VMX-root, then as switching
|
||||
// to another process is not possible, we'll return
|
||||
// an error
|
||||
//
|
||||
if (InputFromVmxRoot && TempPid != PsGetCurrentProcessId())
|
||||
{
|
||||
//
|
||||
// Address is invalid (Set the error)
|
||||
//
|
||||
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DEBUGGER_ERROR_INVALID_ADDRESS;
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_PROCESS_ID_CANNOT_BE_SPECIFIED_WHILE_APPLYING_EVENT_FROM_VMX_ROOT_MODE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Check whether address is valid or not based on whether the event needs
|
||||
// to be applied directly from VMX-root mode or not
|
||||
//
|
||||
if (InputFromVmxRoot)
|
||||
{
|
||||
if (VirtualAddressToPhysicalAddressOnTargetProcess(EventDetails->OptionalParam1) == NULL ||
|
||||
VirtualAddressToPhysicalAddressOnTargetProcess(EventDetails->OptionalParam2) == NULL)
|
||||
{
|
||||
//
|
||||
// Address is invalid (Set the error)
|
||||
//
|
||||
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (VirtualAddressToPhysicalAddressByProcessId(EventDetails->OptionalParam1, TempPid) == NULL ||
|
||||
VirtualAddressToPhysicalAddressByProcessId(EventDetails->OptionalParam2, TempPid) == NULL)
|
||||
{
|
||||
//
|
||||
// Address is invalid (Set the error)
|
||||
//
|
||||
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check if the 'to' is greater that 'from'
|
||||
//
|
||||
if (EventDetails->OptionalParam1 >= EventDetails->OptionalParam2)
|
||||
{
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DEBUGGER_ERROR_INVALID_ADDRESS;
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Create Event
|
||||
// ----------------------------------------------------------------------------------
|
||||
// As we reached, all the checks are passed and it means the event is valid
|
||||
//
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// We initialize event with disabled mode as it doesn't have action yet
|
||||
//
|
||||
if (EventDetails->ConditionBufferSize != 0)
|
||||
{
|
||||
//
|
||||
// Conditional Event
|
||||
//
|
||||
Event = DebuggerCreateEvent(FALSE,
|
||||
EventDetails->CoreId,
|
||||
EventDetails->ProcessId,
|
||||
EventDetails->EventType,
|
||||
EventDetails->Tag,
|
||||
EventDetails->OptionalParam1,
|
||||
EventDetails->OptionalParam2,
|
||||
EventDetails->OptionalParam3,
|
||||
EventDetails->OptionalParam4,
|
||||
EventDetails->ConditionBufferSize,
|
||||
(UINT64)EventDetails + sizeof(DEBUGGER_GENERAL_EVENT_DETAIL));
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Unconditional Event
|
||||
//
|
||||
Event = DebuggerCreateEvent(FALSE,
|
||||
EventDetails->CoreId,
|
||||
EventDetails->ProcessId,
|
||||
EventDetails->EventType,
|
||||
EventDetails->Tag,
|
||||
EventDetails->OptionalParam1,
|
||||
EventDetails->OptionalParam2,
|
||||
EventDetails->OptionalParam3,
|
||||
EventDetails->OptionalParam4,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (Event == NULL)
|
||||
{
|
||||
//
|
||||
// Set the error
|
||||
//
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DEBUGGER_ERROR_UNABLE_TO_CREATE_EVENT;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Register the event
|
||||
//
|
||||
DebuggerRegisterEvent(Event);
|
||||
|
||||
//
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Apply & Enable Event
|
||||
// ----------------------------------------------------------------------------------
|
||||
//
|
||||
/**
|
||||
* @brief Applying events
|
||||
*
|
||||
* @param EventDetails The structure that describes event that came
|
||||
* from the user-mode or VMX-root mode
|
||||
* @param BufferLength Length of the buffer
|
||||
* @param ResultsToReturn Result buffer that should be returned to
|
||||
* the user-mode
|
||||
* @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL
|
||||
*
|
||||
* @return BOOLEAN TRUE if the event was applied otherwise returns FALSE
|
||||
*/
|
||||
BOOLEAN
|
||||
DebuggerApplyEvent(PDEBUGGER_EVENT Event,
|
||||
PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails,
|
||||
UINT32 BufferLength,
|
||||
PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturn,
|
||||
BOOLEAN InputFromVmxRoot)
|
||||
{
|
||||
UINT64 PagesBytes;
|
||||
BOOLEAN ResultOfApplyingEvent = FALSE;
|
||||
|
||||
//
|
||||
// Now we should configure the cpu to generate the events
|
||||
|
|
@ -2447,8 +2476,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
|
|||
default:
|
||||
LogError("Err, Invalid monitor hook type");
|
||||
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DEBUGGER_ERROR_EVENT_TYPE_IS_INVALID;
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_EVENT_TYPE_IS_INVALID;
|
||||
|
||||
goto ClearTheEventAfterCreatingEvent;
|
||||
|
||||
|
|
@ -2500,8 +2529,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
|
|||
//
|
||||
if (!ResultOfApplyingEvent)
|
||||
{
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DebuggerGetLastError();
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DebuggerGetLastError();
|
||||
|
||||
goto ClearTheEventAfterCreatingEvent;
|
||||
}
|
||||
|
|
@ -2528,8 +2557,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
|
|||
// There was an error applying this event, so we're setting
|
||||
// the event
|
||||
//
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DebuggerGetLastError();
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DebuggerGetLastError();
|
||||
goto ClearTheEventAfterCreatingEvent;
|
||||
}
|
||||
|
||||
|
|
@ -2561,8 +2590,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
|
|||
// There was an error applying this event, so we're setting
|
||||
// the event
|
||||
//
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DebuggerGetLastError();
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DebuggerGetLastError();
|
||||
goto ClearTheEventAfterCreatingEvent;
|
||||
}
|
||||
|
||||
|
|
@ -3011,8 +3040,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
|
|||
//
|
||||
// Set the error
|
||||
//
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DEBUGGER_ERROR_EVENT_TYPE_IS_INVALID;
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_EVENT_TYPE_IS_INVALID;
|
||||
goto ClearTheEventAfterCreatingEvent;
|
||||
|
||||
break;
|
||||
|
|
@ -3046,8 +3075,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
|
|||
//
|
||||
// Set the status
|
||||
//
|
||||
ResultsToReturnUsermode->IsSuccessful = TRUE;
|
||||
ResultsToReturnUsermode->Error = 0;
|
||||
ResultsToReturn->IsSuccessful = TRUE;
|
||||
ResultsToReturn->Error = 0;
|
||||
|
||||
//
|
||||
// Event was applied successfully
|
||||
|
|
@ -3056,15 +3085,127 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
|
|||
|
||||
ClearTheEventAfterCreatingEvent:
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Routine for parsing events
|
||||
*
|
||||
* @param EventDetails The structure that describes event that came
|
||||
* from the user-mode
|
||||
* @param BufferLength Length of the buffer
|
||||
* @param ResultsToReturn Result buffer that should be returned to
|
||||
* the user-mode
|
||||
* @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL
|
||||
*
|
||||
* @return BOOLEAN TRUE if the event was valid an regisered without error,
|
||||
* otherwise returns FALSE
|
||||
*/
|
||||
BOOLEAN
|
||||
DebuggerParseEvent(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails,
|
||||
UINT32 BufferLength,
|
||||
PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturn,
|
||||
BOOLEAN InputFromVmxRoot)
|
||||
{
|
||||
PDEBUGGER_EVENT Event;
|
||||
|
||||
//
|
||||
// Remove the event as it was not successfull
|
||||
// ----------------------------------------------------------------------------------
|
||||
// *** Validating the Event's parameters ***
|
||||
// ----------------------------------------------------------------------------------
|
||||
//
|
||||
if (Event != NULL)
|
||||
|
||||
//
|
||||
// Validate the event parameters
|
||||
//
|
||||
if (!DebuggerValidateEvent(EventDetails, BufferLength, ResultsToReturn, InputFromVmxRoot))
|
||||
{
|
||||
DebuggerRemoveEvent(Event->Tag);
|
||||
//
|
||||
// Input event is not valid
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
//
|
||||
// ----------------------------------------------------------------------------------
|
||||
// *** Create Event ***
|
||||
// ----------------------------------------------------------------------------------
|
||||
//
|
||||
|
||||
//
|
||||
// We initialize event with disabled mode as it doesn't have action yet
|
||||
//
|
||||
if (EventDetails->ConditionBufferSize != 0)
|
||||
{
|
||||
//
|
||||
// Conditional Event
|
||||
//
|
||||
Event = DebuggerCreateEvent(FALSE,
|
||||
EventDetails->CoreId,
|
||||
EventDetails->ProcessId,
|
||||
EventDetails->EventType,
|
||||
EventDetails->Tag,
|
||||
EventDetails->OptionalParam1,
|
||||
EventDetails->OptionalParam2,
|
||||
EventDetails->OptionalParam3,
|
||||
EventDetails->OptionalParam4,
|
||||
EventDetails->ConditionBufferSize,
|
||||
(UINT64)EventDetails + sizeof(DEBUGGER_GENERAL_EVENT_DETAIL));
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Unconditional Event
|
||||
//
|
||||
Event = DebuggerCreateEvent(FALSE,
|
||||
EventDetails->CoreId,
|
||||
EventDetails->ProcessId,
|
||||
EventDetails->EventType,
|
||||
EventDetails->Tag,
|
||||
EventDetails->OptionalParam1,
|
||||
EventDetails->OptionalParam2,
|
||||
EventDetails->OptionalParam3,
|
||||
EventDetails->OptionalParam4,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (Event == NULL)
|
||||
{
|
||||
//
|
||||
// Set the error
|
||||
//
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_UNABLE_TO_CREATE_EVENT;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Register the event
|
||||
//
|
||||
DebuggerRegisterEvent(Event);
|
||||
|
||||
//
|
||||
// ----------------------------------------------------------------------------------
|
||||
// *** Apply & Enable Event ***
|
||||
// ----------------------------------------------------------------------------------
|
||||
//
|
||||
if (DebuggerApplyEvent(Event, EventDetails, BufferLength, ResultsToReturn, InputFromVmxRoot))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Remove the event as it was not successfull
|
||||
//
|
||||
if (Event != NULL)
|
||||
{
|
||||
DebuggerRemoveEvent(Event->Tag);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -3075,13 +3216,13 @@ ClearTheEventAfterCreatingEvent:
|
|||
* @param Action Structure that describes the action that comes from the
|
||||
* user-mode
|
||||
* @param BufferLength Length of the buffer that comes from user-mode
|
||||
* @param ResultsToReturnUsermode The buffer address that should be returned
|
||||
* @param ResultsToReturn The buffer address that should be returned
|
||||
* to the user-mode as the result
|
||||
* @return BOOLEAN if action was parsed and added successfully, return TRUE
|
||||
* otherwise, returns FALSE
|
||||
*/
|
||||
BOOLEAN
|
||||
DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLength, PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturnUsermode)
|
||||
DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLength, PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturn)
|
||||
{
|
||||
//
|
||||
// Check if Tag is valid or not
|
||||
|
|
@ -3093,8 +3234,8 @@ DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLe
|
|||
//
|
||||
// Set the appropriate error
|
||||
//
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DEBUGGER_ERROR_TAG_NOT_EXISTS;
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_TAG_NOT_EXISTS;
|
||||
|
||||
//
|
||||
// Show that the
|
||||
|
|
@ -3112,8 +3253,8 @@ DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLe
|
|||
//
|
||||
// Set the appropriate error
|
||||
//
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DEBUGGER_ERROR_ACTION_BUFFER_SIZE_IS_ZERO;
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_ACTION_BUFFER_SIZE_IS_ZERO;
|
||||
|
||||
//
|
||||
// Show that the
|
||||
|
|
@ -3150,8 +3291,8 @@ DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLe
|
|||
//
|
||||
// Set the appropriate error
|
||||
//
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DEBUGGER_ERROR_ACTION_BUFFER_SIZE_IS_ZERO;
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_ACTION_BUFFER_SIZE_IS_ZERO;
|
||||
|
||||
//
|
||||
// Show that the
|
||||
|
|
@ -3192,8 +3333,8 @@ DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLe
|
|||
//
|
||||
// Set the appropriate error
|
||||
//
|
||||
ResultsToReturnUsermode->IsSuccessful = FALSE;
|
||||
ResultsToReturnUsermode->Error = DEBUGGER_ERROR_INVALID_ACTION_TYPE;
|
||||
ResultsToReturn->IsSuccessful = FALSE;
|
||||
ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ACTION_TYPE;
|
||||
|
||||
//
|
||||
// Show that the
|
||||
|
|
@ -3201,8 +3342,8 @@ DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLe
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
ResultsToReturnUsermode->IsSuccessful = TRUE;
|
||||
ResultsToReturnUsermode->Error = 0;
|
||||
ResultsToReturn->IsSuccessful = TRUE;
|
||||
ResultsToReturn->Error = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,24 +32,108 @@ HaltedCorePerformTargetTask(PROCESSOR_DEBUGGING_STATE * DbgState,
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Broadcast tasks to halted cores
|
||||
* @brief Run the task on a single halted core
|
||||
* @details This function should be called from VMX root-mode
|
||||
*
|
||||
* @param DbgState The state of the debugger on the current core
|
||||
* @param TargetCoreId The target core's ID (to just run on this core)
|
||||
* @param TargetTask The target task
|
||||
* @param LockAgainAfterTask Lock the core after the task
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
HaltedCoreBroadcasTaskToAllCores(PROCESSOR_DEBUGGING_STATE * DbgState,
|
||||
UINT32 TargetTask,
|
||||
BOOLEAN LockAgainAfterTask)
|
||||
HaltedCoreApplyTaskOnTargetCore(UINT32 TargetCoreId,
|
||||
UINT32 TargetTask,
|
||||
BOOLEAN LockAgainAfterTask)
|
||||
{
|
||||
PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[TargetCoreId];
|
||||
|
||||
//
|
||||
// Activate running the halted task
|
||||
//
|
||||
DbgState->HaltedCoreTask.PerformHaltedTask = TRUE;
|
||||
|
||||
DbgState->HaltedCoreTask.KernelStatus = NULL;
|
||||
DbgState->HaltedCoreTask.LockAgainAfterTask = LockAgainAfterTask;
|
||||
DbgState->HaltedCoreTask.TargetTask = TargetTask;
|
||||
|
||||
//
|
||||
// Unlock halted core
|
||||
//
|
||||
KdUnlockTheHaltedCore(DbgState);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Run the task on a single halted core
|
||||
* @details This function should be called from VMX root-mode
|
||||
*
|
||||
* @param TargetCoreId The target core's ID (to just run on this core)
|
||||
* @param TargetTask The target task
|
||||
* @param LockAgainAfterTask Lock the core after the task
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
HaltedCoreRunTaskOnSingleCore(UINT32 TargetCoreId,
|
||||
UINT32 TargetTask,
|
||||
BOOLEAN LockAgainAfterTask)
|
||||
{
|
||||
//
|
||||
// Check if the task needs to be executed for the current
|
||||
// core or any other cores
|
||||
//
|
||||
if (TargetCoreId == KeGetCurrentProcessorNumberEx(NULL))
|
||||
{
|
||||
//
|
||||
// *** Perform the task for the current core ***
|
||||
//
|
||||
HaltedCorePerformTargetTask(&g_DbgState[TargetCoreId], TargetTask);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// *** Perform the task for another core ***
|
||||
//
|
||||
|
||||
//
|
||||
// apply task to the target core
|
||||
//
|
||||
HaltedCoreApplyTaskOnTargetCore(TargetCoreId, TargetTask, LockAgainAfterTask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Broadcast tasks to halted cores
|
||||
* @details This function should be called from VMX root-mode
|
||||
*
|
||||
* @param DbgState The state of the debugger on the current core
|
||||
* @param TargetTask The target task
|
||||
* @param LockAgainAfterTask Lock the core after the task
|
||||
* @param Synchronize Whether the function should wait for all cores to synchronize
|
||||
* and lock again or not
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
HaltedCoreBroadcastTaskAllCores(PROCESSOR_DEBUGGING_STATE * DbgState,
|
||||
UINT32 TargetTask,
|
||||
BOOLEAN LockAgainAfterTask,
|
||||
BOOLEAN Synchronize)
|
||||
{
|
||||
ULONG CoreCount;
|
||||
|
||||
CoreCount = KeQueryActiveProcessorCount(0);
|
||||
|
||||
//
|
||||
// Synchronization is not possible when the locking after the task is
|
||||
// not expected
|
||||
//
|
||||
if (Synchronize && !LockAgainAfterTask)
|
||||
{
|
||||
LogWarning("Synchronization is not possible when the locking after the task is not expected");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Apply the task to all cores except current core
|
||||
//
|
||||
|
|
@ -58,23 +142,53 @@ HaltedCoreBroadcasTaskToAllCores(PROCESSOR_DEBUGGING_STATE * DbgState,
|
|||
if (DbgState->CoreId != i)
|
||||
{
|
||||
//
|
||||
// Activate running the halted task
|
||||
// apply task to the target core
|
||||
//
|
||||
g_DbgState[i].HaltedCoreTask.PerformHaltedTask = TRUE;
|
||||
|
||||
g_DbgState[i].HaltedCoreTask.KernelStatus = NULL;
|
||||
g_DbgState[i].HaltedCoreTask.LockAgainAfterTask = LockAgainAfterTask;
|
||||
g_DbgState[i].HaltedCoreTask.TargetTask = TargetTask;
|
||||
|
||||
HaltedCoreApplyTaskOnTargetCore(i, TargetTask, LockAgainAfterTask);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Unlock halted core
|
||||
// Perform the task for the current core
|
||||
//
|
||||
KdUnlockTheHaltedCore(&g_DbgState[i]);
|
||||
HaltedCorePerformTargetTask(DbgState, TargetTask);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Perform the task for the current core
|
||||
// If synchronization is expected, we need to check to make sure
|
||||
// all cores are synchronized (locked) at this point or not
|
||||
//
|
||||
HaltedCorePerformTargetTask(DbgState, TargetTask);
|
||||
if (Synchronize)
|
||||
{
|
||||
for (size_t i = 0; i < CoreCount; i++)
|
||||
{
|
||||
if (DbgState->CoreId != i)
|
||||
{
|
||||
//
|
||||
// Wait until the core is locked again
|
||||
//
|
||||
while (TRUE)
|
||||
{
|
||||
//
|
||||
// Keep checking to make sure the target core finished the
|
||||
// execution its task and locked again
|
||||
//
|
||||
if (KdCheckTheHaltedCore(&g_DbgState[i]) == FALSE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// All cores locked again
|
||||
//
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1591,7 +1591,7 @@ KdQuerySystemState()
|
|||
|
||||
for (size_t i = 0; i < CoreCount; i++)
|
||||
{
|
||||
if (g_DbgState[i].Lock)
|
||||
if (SpinlockCheckLock(&g_DbgState[i].Lock))
|
||||
{
|
||||
LogInfo("Core : %d is locked", i);
|
||||
}
|
||||
|
|
@ -1623,7 +1623,7 @@ KdQuerySystemState()
|
|||
/**
|
||||
* @brief unlock the target core
|
||||
*
|
||||
* @param DbgState The state of the debugger on the current core
|
||||
* @param DbgState The state of the debugger on the target core
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
|
|
@ -1633,6 +1633,19 @@ KdUnlockTheHaltedCore(PROCESSOR_DEBUGGING_STATE * DbgState)
|
|||
SpinlockUnlock(&DbgState->Lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief check the lock state of the target core
|
||||
*
|
||||
* @param DbgState The state of the debugger on the target core
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
KdCheckTheHaltedCore(PROCESSOR_DEBUGGING_STATE * DbgState)
|
||||
{
|
||||
return SpinlockCheckLock(&DbgState->Lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief routines to break page-in
|
||||
*
|
||||
|
|
@ -1680,6 +1693,150 @@ KdBringPagein(PROCESSOR_DEBUGGING_STATE * DbgState,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform the test packet's operation
|
||||
*
|
||||
* @param DbgState The state of the debugger on the current core
|
||||
* @param TestQueryPacket test packet request
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
KdPerformTheTestPacketOperation(PROCESSOR_DEBUGGING_STATE * DbgState,
|
||||
DEBUGGER_DEBUGGER_TEST_QUERY_BUFFER * TestQueryPacket)
|
||||
{
|
||||
//
|
||||
// Dispatch the request
|
||||
//
|
||||
switch (TestQueryPacket->RequestType)
|
||||
{
|
||||
case TEST_QUERY_HALTING_CORE_STATUS:
|
||||
|
||||
//
|
||||
// Query state of the system
|
||||
//
|
||||
KdQuerySystemState();
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
|
||||
case TEST_QUERY_TRAP_STATE:
|
||||
|
||||
//
|
||||
// Query state of the trap
|
||||
//
|
||||
KdQueryRflagTrapState();
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
|
||||
case TEST_QUERY_PREALLOCATED_POOL_STATE:
|
||||
|
||||
//
|
||||
// Query state of pre-allocated pools
|
||||
//
|
||||
PoolManagerShowPreAllocatedPools();
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
|
||||
case TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_SYNCHRONOUS:
|
||||
case TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_ASYNCHRONOUS:
|
||||
|
||||
//
|
||||
// Send request for the target task to the halted cores (synchronized and unsynchronized)
|
||||
//
|
||||
HaltedCoreBroadcastTaskAllCores(DbgState,
|
||||
0x55,
|
||||
TRUE,
|
||||
TestQueryPacket->RequestType == TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_SYNCHRONOUS ? TRUE : FALSE);
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
|
||||
case TEST_SETTING_TARGET_TASKS_ON_TARGET_HALTED_CORES:
|
||||
|
||||
//
|
||||
// Validate core number
|
||||
//
|
||||
if (!CommonValidateCoreNumber(TestQueryPacket->Context))
|
||||
{
|
||||
//
|
||||
// Core number is invalid
|
||||
//
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_ERROR_INVALID_CORE_ID;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Send request for the target task to the target halted core
|
||||
//
|
||||
HaltedCoreRunTaskOnSingleCore((UINT32)TestQueryPacket->Context, 0x8585, TRUE);
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TEST_BREAKPOINT_TURN_OFF_BPS:
|
||||
|
||||
//
|
||||
// Turn off the breakpoint interception
|
||||
//
|
||||
g_InterceptBreakpoints = TRUE;
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
|
||||
case TEST_BREAKPOINT_TURN_ON_BPS:
|
||||
|
||||
//
|
||||
// Turn on the breakpoint interception
|
||||
//
|
||||
g_InterceptBreakpoints = FALSE;
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
|
||||
case TEST_BREAKPOINT_TURN_OFF_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER:
|
||||
|
||||
//
|
||||
// Turn off the breakpoints and events interception before executing the commands in the remote computer
|
||||
//
|
||||
g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer = TRUE;
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
|
||||
case TEST_BREAKPOINT_TURN_ON_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER:
|
||||
|
||||
//
|
||||
// Turn on the breakpoints and events interception after finishing the commands in the remote computer
|
||||
//
|
||||
g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer = FALSE;
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
//
|
||||
// Query index not found
|
||||
//
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_ERROR_UNKNOWN_TEST_QUERY_RECEIVED;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform modify the state of short-circuiting
|
||||
*
|
||||
|
|
@ -2168,107 +2325,9 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState)
|
|||
TestQueryPacket = (DEBUGGER_DEBUGGER_TEST_QUERY_BUFFER *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET));
|
||||
|
||||
//
|
||||
// Dispatch the request
|
||||
// Perform the test packet operation
|
||||
//
|
||||
switch (TestQueryPacket->RequestType)
|
||||
{
|
||||
case TEST_QUERY_HALTING_CORE_STATUS:
|
||||
|
||||
//
|
||||
// Query state of the system
|
||||
//
|
||||
KdQuerySystemState();
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
|
||||
case TEST_QUERY_TRAP_STATE:
|
||||
|
||||
//
|
||||
// Query state of the trap
|
||||
//
|
||||
KdQueryRflagTrapState();
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
|
||||
case TEST_QUERY_PREALLOCATED_POOL_STATE:
|
||||
|
||||
//
|
||||
// Query state of pre-allocated pools
|
||||
//
|
||||
PoolManagerShowPreAllocatedPools();
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
|
||||
case TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES:
|
||||
|
||||
//
|
||||
// Send request for the target task to the halted cores
|
||||
//
|
||||
HaltedCoreBroadcasTaskToAllCores(DbgState, 0x55, TRUE);
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
|
||||
case TEST_BREAKPOINT_TURN_OFF_BPS:
|
||||
|
||||
//
|
||||
// Turn off the breakpoint interception
|
||||
//
|
||||
g_InterceptBreakpoints = TRUE;
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
|
||||
case TEST_BREAKPOINT_TURN_ON_BPS:
|
||||
|
||||
//
|
||||
// Turn on the breakpoint interception
|
||||
//
|
||||
g_InterceptBreakpoints = FALSE;
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
|
||||
case TEST_BREAKPOINT_TURN_OFF_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER:
|
||||
|
||||
//
|
||||
// Turn off the breakpoints and events interception before executing the commands in the remote computer
|
||||
//
|
||||
g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer = TRUE;
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
|
||||
case TEST_BREAKPOINT_TURN_ON_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER:
|
||||
|
||||
//
|
||||
// Turn on the breakpoints and events interception after finishing the commands in the remote computer
|
||||
//
|
||||
g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer = FALSE;
|
||||
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
//
|
||||
// Query index not found
|
||||
//
|
||||
TestQueryPacket->KernelStatus = DEBUGGER_ERROR_UNKNOWN_TEST_QUERY_RECEIVED;
|
||||
|
||||
break;
|
||||
}
|
||||
KdPerformTheTestPacketOperation(DbgState, TestQueryPacket);
|
||||
|
||||
//
|
||||
// Send the result of query system state to the debuggee
|
||||
|
|
|
|||
|
|
@ -310,11 +310,12 @@ DrvDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|||
|
||||
//
|
||||
// Both usermode and to send to usermode and the comming buffer are
|
||||
// at the same place
|
||||
// at the same place (not comming from the VMX-root mode)
|
||||
//
|
||||
DebuggerParseEventFromUsermode(DebuggerNewEventRequest,
|
||||
InBuffLength,
|
||||
(PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER)Irp->AssociatedIrp.SystemBuffer);
|
||||
DebuggerParseEvent(DebuggerNewEventRequest,
|
||||
InBuffLength,
|
||||
(PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER)Irp->AssociatedIrp.SystemBuffer,
|
||||
FALSE);
|
||||
|
||||
Irp->IoStatus.Information = sizeof(DEBUGGER_EVENT_AND_ACTION_REG_BUFFER);
|
||||
Status = STATUS_SUCCESS;
|
||||
|
|
|
|||
|
|
@ -98,3 +98,6 @@ CommonGetProcessNameFromProcessControlBlock(PEPROCESS Eprocess);
|
|||
|
||||
BOOLEAN
|
||||
CommonKillProcess(UINT32 ProcessId, PROCESS_KILL_METHODS KillingMethod);
|
||||
|
||||
BOOLEAN
|
||||
CommonValidateCoreNumber(UINT32 CoreNumber);
|
||||
|
|
|
|||
|
|
@ -220,10 +220,13 @@ BOOLEAN
|
|||
DebuggerQueryDebuggerStatus();
|
||||
|
||||
BOOLEAN
|
||||
DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT32 BufferLength, PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturnUsermode);
|
||||
DebuggerParseEvent(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails,
|
||||
UINT32 BufferLength,
|
||||
PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturn,
|
||||
BOOLEAN InputFromVmxRoot);
|
||||
|
||||
BOOLEAN
|
||||
DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLength, PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturnUsermode);
|
||||
DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLength, PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturn);
|
||||
|
||||
BOOLEAN
|
||||
DebuggerParseEventsModificationFromUsermode(PDEBUGGER_MODIFY_EVENTS DebuggerEventModificationRequest);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,12 @@ HaltedCorePerformTargetTask(PROCESSOR_DEBUGGING_STATE * DbgState,
|
|||
UINT32 TargetTask);
|
||||
|
||||
VOID
|
||||
HaltedCoreBroadcasTaskToAllCores(PROCESSOR_DEBUGGING_STATE * DbgState,
|
||||
UINT32 TargetTask,
|
||||
BOOLEAN LockAgainAfterTask);
|
||||
HaltedCoreRunTaskOnSingleCore(UINT32 TargetCoreId,
|
||||
UINT32 TargetTask,
|
||||
BOOLEAN LockAgainAfterTask);
|
||||
|
||||
BOOLEAN
|
||||
HaltedCoreBroadcastTaskAllCores(PROCESSOR_DEBUGGING_STATE * DbgState,
|
||||
UINT32 TargetTask,
|
||||
BOOLEAN LockAgainAfterTask,
|
||||
BOOLEAN Synchronize);
|
||||
|
|
|
|||
|
|
@ -230,6 +230,9 @@ KdHandleNmiBroadcastDebugBreaks(UINT32 CoreId, BOOLEAN IsOnVmxNmiHandler);
|
|||
VOID
|
||||
KdUnlockTheHaltedCore(PROCESSOR_DEBUGGING_STATE * DbgState);
|
||||
|
||||
BOOLEAN
|
||||
KdCheckTheHaltedCore(PROCESSOR_DEBUGGING_STATE * DbgState);
|
||||
|
||||
BOOLEAN
|
||||
KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId(UINT32 CoreId,
|
||||
DEBUGGER_THREAD_PROCESS_TRACING TracingType);
|
||||
|
|
|
|||
|
|
@ -422,6 +422,12 @@
|
|||
*/
|
||||
#define DEBUGGER_ERROR_MODE_EXECUTION_IS_INVALID 0xc000003f
|
||||
|
||||
/**
|
||||
* @brief error, the process id cannot be specified while the debugger is in VMX-root mode
|
||||
*
|
||||
*/
|
||||
#define DEBUGGER_ERROR_PROCESS_ID_CANNOT_BE_SPECIFIED_WHILE_APPLYING_EVENT_FROM_VMX_ROOT_MODE 0xc0000040
|
||||
|
||||
//
|
||||
// WHEN YOU ADD ANYTHING TO THIS LIST OF ERRORS, THEN
|
||||
// MAKE SURE TO ADD AN ERROR MESSAGE TO ShowErrorMessage(UINT32 Error)
|
||||
|
|
|
|||
|
|
@ -266,14 +266,16 @@ typedef struct _DEBUGGER_FLUSH_LOGGING_BUFFERS
|
|||
*/
|
||||
typedef enum _DEBUGGER_TEST_QUERY_STATE
|
||||
{
|
||||
TEST_QUERY_HALTING_CORE_STATUS = 1, // Query constant to show detail of halting of core
|
||||
TEST_QUERY_PREALLOCATED_POOL_STATE = 2, // Query pre-allocated pool state
|
||||
TEST_QUERY_TRAP_STATE = 3, // Query trap state
|
||||
TEST_BREAKPOINT_TURN_OFF_BPS = 4, // Turn off the breakpoints
|
||||
TEST_BREAKPOINT_TURN_ON_BPS = 5, // Turn on the breakpoints
|
||||
TEST_BREAKPOINT_TURN_OFF_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER = 6, // Turn off the breakpoints and events for executing the commands in the remote computer
|
||||
TEST_BREAKPOINT_TURN_ON_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER = 7, // Turn on the breakpoints and events for executing the commands in the remote computer
|
||||
TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES = 8, // For test purposes
|
||||
TEST_QUERY_HALTING_CORE_STATUS = 1, // Query constant to show detail of halting of core
|
||||
TEST_QUERY_PREALLOCATED_POOL_STATE = 2, // Query pre-allocated pool state
|
||||
TEST_QUERY_TRAP_STATE = 3, // Query trap state
|
||||
TEST_BREAKPOINT_TURN_OFF_BPS = 4, // Turn off the breakpoints
|
||||
TEST_BREAKPOINT_TURN_ON_BPS = 5, // Turn on the breakpoints
|
||||
TEST_BREAKPOINT_TURN_OFF_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER = 6, // Turn off the breakpoints and events for executing the commands in the remote computer
|
||||
TEST_BREAKPOINT_TURN_ON_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER = 7, // Turn on the breakpoints and events for executing the commands in the remote computer
|
||||
TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_SYNCHRONOUS = 8, // For testing synchronized event
|
||||
TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_ASYNCHRONOUS = 9, // For testing unsynchronized event
|
||||
TEST_SETTING_TARGET_TASKS_ON_TARGET_HALTED_CORES = 10, // Send the task to the halted core
|
||||
|
||||
} DEBUGGER_TEST_QUERY_STATE;
|
||||
|
||||
|
|
@ -284,6 +286,7 @@ typedef enum _DEBUGGER_TEST_QUERY_STATE
|
|||
typedef struct _DEBUGGER_DEBUGGER_TEST_QUERY_BUFFER
|
||||
{
|
||||
DEBUGGER_TEST_QUERY_STATE RequestType;
|
||||
UINT64 Context;
|
||||
UINT32 KernelStatus;
|
||||
|
||||
} DEBUGGER_DEBUGGER_TEST_QUERY_BUFFER, *PDEBUGGER_DEBUGGER_TEST_QUERY_BUFFER;
|
||||
|
|
|
|||
|
|
@ -159,3 +159,21 @@ SpinlockUnlock(volatile LONG * Lock)
|
|||
{
|
||||
*Lock = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check the lock without changing the state
|
||||
*
|
||||
* @param LONG Lock variable
|
||||
*/
|
||||
BOOLEAN
|
||||
SpinlockCheckLock(volatile LONG * Lock)
|
||||
{
|
||||
if (*Lock)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@
|
|||
BOOLEAN
|
||||
SpinlockTryLock(volatile LONG * Lock);
|
||||
|
||||
BOOLEAN
|
||||
SpinlockCheckLock(volatile LONG * Lock);
|
||||
|
||||
void
|
||||
SpinlockLock(volatile LONG * Lock);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue