Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/SharpDbg.Infrastructure/Debugger/ManagedDebugger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public partial class ManagedDebugger : IDisposable
private int? _pendingAttachProcessId;
private AsyncStepper? _asyncStepper;
private CompiledExpressionInterpreter? _expressionInterpreter;
private bool _stopAtEntryActive;
private bool _stopAtEntrySignaled;

public event Action<int, string>? OnStopped;
// ThreadId, FilePath, Line, Reason
Expand Down Expand Up @@ -98,6 +100,11 @@ private void PerformAttach(int processId)

private void ContinueProcess()
{
if (_stopAtEntryActive && _stopAtEntrySignaled)
{
_logger?.Invoke("Auto-continue suppressed (stop-at-entry signaled)");
return;
}
if (_rawProcess != null)
{
IsRunning = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,25 @@ private void HandleProcessCreated(object? sender, CreateProcessCorDebugManagedCa
{
_logger?.Invoke("Process created event");
_rawProcess = createProcessCorDebugManagedCallbackEventArgs.Process;
CorDebugThread? corThread = null;
foreach (var thread in _rawProcess.EnumerateThreads())
{
corThread = thread;
break;
}
if (corThread != null)
{
_threads[corThread.Id] = corThread;
OnThreadStarted?.Invoke(corThread.Id, $"Thread {corThread.Id}");
}

if (_stopAtEntryActive && !_stopAtEntrySignaled && corThread != null)
{
_stopAtEntrySignaled = true;
IsRunning = false;
OnStopped?.Invoke(corThread.Id, "entry");
return;
}

ContinueProcess();
}
Expand All @@ -27,6 +46,13 @@ private void HandleThreadCreated(object? sender, CreateThreadCorDebugManagedCall
var corThread = createThreadCorDebugManagedCallbackEventArgs.Thread;
_threads[corThread.Id] = corThread;
OnThreadStarted?.Invoke(corThread.Id, $"Thread {corThread.Id}");
if (_stopAtEntryActive && !_stopAtEntrySignaled)
{
_stopAtEntrySignaled = true;
IsRunning = false;
OnStopped?.Invoke(corThread.Id, "entry");
return;
}
ContinueProcess();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ private void PerformLaunch()
_pendingLaunchProgram = null;
_pendingLaunchArgs = null;
_pendingLaunchWorkingDirectory = null;
_stopAtEntryActive = stopAtEntry;
_stopAtEntrySignaled = false;

// Build command line: "program" "arg1" "arg2" ...
var commandLine = new StringBuilder();
Expand Down Expand Up @@ -191,6 +193,11 @@ public void Continue()
_logger?.Invoke("Continue");
if (_rawProcess != null)
{
if (_stopAtEntryActive)
{
_stopAtEntryActive = false;
_stopAtEntrySignaled = false;
}
IsRunning = true;
_variableManager.ClearAndDisposeHandleValues();
_rawProcess.Continue(false);
Expand All @@ -217,6 +224,11 @@ public void Pause()
public async void StepNext(int threadId)
{
_logger?.Invoke($"StepNext on thread {threadId}");
if (_stopAtEntryActive)
{
_stopAtEntryActive = false;
_stopAtEntrySignaled = false;
}
if (_threads.TryGetValue(threadId, out var thread))
{
var frame = thread.ActiveFrame;
Expand Down Expand Up @@ -250,6 +262,11 @@ public async void StepNext(int threadId)
public async void StepIn(int threadId)
{
_logger?.Invoke($"StepIn on thread {threadId}");
if (_stopAtEntryActive)
{
_stopAtEntryActive = false;
_stopAtEntrySignaled = false;
}
if (_threads.TryGetValue(threadId, out var thread))
{
var frame = thread.ActiveFrame;
Expand Down Expand Up @@ -283,6 +300,11 @@ public async void StepIn(int threadId)
public async void StepOut(int threadId)
{
_logger?.Invoke($"StepOut on thread {threadId}");
if (_stopAtEntryActive)
{
_stopAtEntryActive = false;
_stopAtEntrySignaled = false;
}
if (_threads.TryGetValue(threadId, out var thread))
{
var frame = thread.ActiveFrame;
Expand Down
38 changes: 38 additions & 0 deletions tests/SharpDbg.Cli.Tests/StopAtEntryTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using AwesomeAssertions;
using SharpDbg.Cli.Tests.Helpers;

namespace SharpDbg.Cli.Tests;

public class StopAtEntryTests(ITestOutputHelper testOutputHelper)
{
[Fact]
public async Task StopAtEntry_ResumeContinues_AndHitsBreakpoint()
{
var startSuspended = true;

var (debugProtocolHost, initializedEventTcs, stoppedEventTcs, adapter, p2) = TestHelper.GetRunningDebugProtocolHostInProc(testOutputHelper, startSuspended);
using var _ = adapter;
using var __ = new ProcessKiller(p2);

await debugProtocolHost
.WithInitializeRequest()
.WithAttachRequest(p2.Id)
.WaitForInitializedEvent(initializedEventTcs);

// Compute a sensible breakpoint line inside Program.cs (the "Log2" WriteLine)
var programPath = Path.JoinFromGitRoot("tests", "DebuggableConsoleApp", "Program.cs");
var lines = File.ReadAllLines(programPath);
var bpLine = Array.FindIndex(lines, l => l.Contains("Log2")) + 1;
if (bpLine == 0) bpLine = 4; // fallback

debugProtocolHost.WithBreakpointsRequest(bpLine, programPath)
.WithConfigurationDoneRequest()
.WithOptionalResumeRuntime(p2.Id, startSuspended);

// Now we should hit the breakpoint we just set
var stoppedEvent2 = await debugProtocolHost.WaitForStoppedEvent(stoppedEventTcs).WaitAsync(TimeSpan.FromSeconds(15));
var stopInfo2 = stoppedEvent2.ReadStopInfo();
stopInfo2.filePath.Should().EndWith("Program.cs");
stopInfo2.line.Should().Be(bpLine);
}
}