Merged
Conversation
Create a new debug adapter that uses the native Windows Debug API (CreateProcess with DEBUG_PROCESS, WaitForDebugEvent, ContinueDebugEvent, etc.) for debugging Windows PE binaries. Features: - Process creation and attach support - Software breakpoints using INT3 instruction - Hardware breakpoints using debug registers (DR0-DR3) - Register read/write for x86 and x64 - Memory read/write - Module tracking (DLL load/unload events) - Thread tracking (create/exit thread events) - Single stepping support - Exception handling Fixes #965 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move process creation to debug thread (required by Windows Debug API) - Add proper condition variable notification on Quit/Detach to prevent deadlock - Add debug logging for troubleshooting Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Shadow breakpoint bytes in ReadMemory for correct disassembly - Fix step-over breakpoint logic for Go() and StepInto() - Fix originalByte not being saved (add bp to vector before ApplyBreakpoint) - Add Reset() function for proper state cleanup on restart - Implement proper stack walking with StackWalk64 - Populate module name in stack frames Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add IsCallInstruction() to decode x86/x64 call opcodes - Add GetReturnAddress() to read return address from stack - Add SetTempBreakpoint()/RemoveTempBreakpoint() for one-time breakpoints - StepOver: set temp breakpoint after call instruction, or single step - StepReturn: set temp breakpoint at return address - Handle temp breakpoint in exception handler - Shadow temp breakpoint in ReadMemory Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Load dbghelp.dll via delay load instead of IAT to avoid conflicts with the DbgEng adapter. A delay load hook tries to load from debugger.x64dbgEngPath or the bundled dbgeng folder first, falling back to system32 if unavailable. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When applying breakpoints, always read the original byte from target memory instead of relying on previously stored values. This fixes issues where: - Breakpoints added before debugging weren't properly applied - Double-application could overwrite the saved original with INT3 The fix ensures ApplyBreakpoint reads from memory and only saves the byte if it's not already an INT3, protecting against corruption. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Windows Native adapter now honors the debugger settings: - If stopAtEntryPoint is true, adds a breakpoint at program entry point - If stopAtSystemEntryPoint is false, continues past the initial breakpoint This matches the behavior of the DbgEng adapter. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Two issues fixed: 1. In Reset(), also clear originalByte to 0 since it's stale for a new process 2. In ApplyPendingBreakpoints(), re-apply existing breakpoints that have isActive=false (from previous debug session) before processing pending ones This ensures breakpoints persist and work correctly across debug session restarts. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Two fixes for hardware breakpoints: 1. Step-over stuck issue: When a hardware breakpoint is hit, temporarily disable it in DR7, single-step past it, then re-enable. This prevents the CPU from immediately hitting the same breakpoint again on resume. 2. Restart issue: Re-apply inactive hardware breakpoints when a new debug session starts, similar to software breakpoints. Also fixed AddHardwareBreakpoint to re-apply existing inactive breakpoints. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Detect WOW64 processes using IsWow64Process and cache the result - Use Wow64GetThreadContext/Wow64SetThreadContext with WOW64_CONTEXT for 32-bit processes running on 64-bit Windows - Update register operations to use correct context type (eax vs rax, etc.) - Handle STATUS_WX86_BREAKPOINT (0x4000001F) and STATUS_WX86_SINGLE_STEP (0x4000001E) exception codes used by WOW64 instead of the standard EXCEPTION_BREAKPOINT and EXCEPTION_SINGLE_STEP - Update hardware breakpoint operations to use WOW64_CONTEXT - Fix stack walking to use correct machine type and context for 32-bit - Replace compile-time _WIN64 checks with runtime m_isTargetWow64 checks Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
WOW64 processes have two system breakpoints: the 64-bit ntdll breakpoint and a second one in 32-bit ntdll (LdrpDoDebuggerBreak). Add tracking for the WOW64 initial breakpoint so it respects the stopAtSystemEntryPoint setting instead of causing an unexpected stop. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use GetFramesOfThread (StackWalk64) to get the return address reliably instead of just reading from the stack pointer. This handles functions with frame pointer omission, different calling conventions, and optimized code. Falls back to simple stack read if unwinding fails. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix Attach() to use the pid parameter directly instead of reading from settings, which would be 0 since the adapter doesn't exist yet when the PID is set via the debugger state - Always stop at the initial breakpoint when attaching to a running process, regardless of stopAtSystemEntryPoint setting (that setting only applies when launching a new process) - Add detailed logging to ApplyBreakpoint to help diagnose breakpoint application failures (logs memory read, protection change, and INT3 write failures with error codes) - Post ResumeEventType event in Go() so the UI shows the target as running - Post StepIntoEventType event in StepInto() so the UI properly updates These fixes enable proper attach workflow and ensure the UI correctly reflects the target's running state. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
When stepping over a software breakpoint, suspend all other threads before removing the INT3 instruction, then resume them after re-applying it. This prevents race conditions where: - Another thread could execute the breakpoint location while INT3 is removed - Temporary breakpoints might not be removed properly - INT3 breakpoints might not be restored before resuming Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add GetProcessCommandLine() helper that uses NtQueryInformationProcess with ProcessCommandLineInformation (available since Windows 8.1). This is cleaner than manually reading the PEB and only requires PROCESS_QUERY_LIMITED_INFORMATION rights, allowing it to work on more processes. Fallback to just the executable name if: - Cannot open the process handle (e.g., protected processes) - NtQueryInformationProcess fails - System processes (PID 0 or 4) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
When stepping (StepInto, StepOver, StepReturn), suspend all other threads to prevent them from hitting breakpoints unexpectedly. Only the thread being stepped executes. When using Go() without a temp breakpoint, all threads run freely. This implements behavior similar to GDB's "scheduler-locking step" mode: - StepInto: Only current thread runs - StepOver/StepReturn: Only current thread runs (via temp breakpoint + Go) - Go() from user: All threads run freely - When step completes: Resume all threads Fixes the issue where stepping one thread would unexpectedly stop because another thread hit a breakpoint. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
When stopped at a breakpoint location (e.g., stepped onto it via single-step), the INT3 instruction is still in memory. When StepInto() or Go() tries to step over the breakpoint, it sets the trap flag but the INT3 is still there. Result: CPU executes and immediately hits the INT3, causing a BREAKPOINT exception instead of single-stepping the actual instruction. This required TWO steps to advance past the breakpoint: 1. First step: Hit INT3, remove it, set IP back - stop at same location 2. Second step: Actually execute the instruction and advance Fix: Call RemoveBreakpointInternal() before setting trap flag in both StepInto() and Go(). Now one step executes exactly one instruction. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…kpoint thread suspension When StepOver() steps over a call with a breakpoint, it: 1. Sets temp breakpoint at return address (m_hasTempBreakpoint = true) 2. Calls Go() 3. Go() was suspending ALL other threads for the entire function execution 4. If the function waits on another thread or acquires a lock held by suspended thread → DEADLOCK The bug: Go() suspended threads when m_hasTempBreakpoint was set, keeping them suspended while the entire function executes, not just for a single instruction. The fix: Remove thread suspension for temp breakpoints (StepOver/StepReturn). Scheduler-locking should only apply to StepInto() which executes one instruction. StepOver/StepReturn internally do a "continue" operation, so all threads should run normally. If another thread hits a breakpoint during StepOver, the debugger stops - this is expected behavior, matching GDB and other debuggers. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Previously, all exceptions including EXCEPTION_INT_DIVIDE_BY_ZERO and EXCEPTION_FLT_DIVIDE_BY_ZERO were incorrectly mapped to AccessViolation. This caused the test_exception_divzero test to fail. Now properly categorize exceptions: - Calculation exceptions (divide by zero, overflow, FPU errors) → Calculation - Illegal instruction exceptions → IllegalInstruction - Memory access violations and fatal exceptions → AccessViolation This matches the expected behavior where divide-by-zero should report DebugStopReason.Calculation, not AccessViolation. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added a new "common.verboseLogging" setting (defaults to false) to control extensive debug output from the Windows Native adapter. Changes: - Added LogVerbose() template method that checks m_verboseLogging flag - Registered "common.verboseLogging" boolean setting in adapter settings - Replaced verbose LogWarn/LogDebug calls with LogVerbose() - Kept actual warnings (errors, failures) as LogWarn When verbose logging is disabled (default), the adapter only logs errors and warnings. When enabled, it logs detailed information about debug events, process creation, module loading, exception handling, etc. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add debugger.defaultWindowsAdapter setting to allow users to choose between WINDOWS_NATIVE and DBGENG adapters. The setting defaults to WINDOWS_NATIVE. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #965