Skip to content

Commit

Permalink
bugfix: proc: propagate debug events we don't cause back to the targe…
Browse files Browse the repository at this point in the history
…t process

Fixes: #594
  • Loading branch information
aarzilli committed Sep 12, 2016
1 parent 8274263 commit 8ef7d9e
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 4 deletions.
22 changes: 22 additions & 0 deletions _fixtures/issue594.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package main

import (
"fmt"
"runtime"
)

func dontsegfault() {
var p *int
func() int {
defer func() {
recover()
}()
return *p
}()
}

func main() {
dontsegfault()
runtime.Breakpoint()
fmt.Println("should stop here")
}
14 changes: 14 additions & 0 deletions proc/proc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1909,3 +1909,17 @@ func TestTestvariables2Prologue(t *testing.T) {
}
})
}

func TestIssue594(t *testing.T) {
// Exceptions that aren't caused by breakpoints should be propagated
// back to the target.
// In particular the target should be able to cause a nil pointer
// dereference panic and recover from it.
withTestProcess("issue594", t, func(p *Process, fixture protest.Fixture) {
assertNoError(p.Continue(), t, "Continue()")
f, ln := currentLineNumber(p, t)
if ln != 21 {
t.Fatalf("Program stopped at %s:%d, expected :21", f, ln)
}
})
}
14 changes: 10 additions & 4 deletions proc/proc_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ func (dbp *Process) waitForDebugEvent(flags waitForDebugEventFlags) (threadID, e
var debugEvent _DEBUG_EVENT
shouldExit := false
for {
continueStatus := uint32(_DBG_CONTINUE)
var milliseconds uint32 = 0
if flags&waitBlocking != 0 {
milliseconds = syscall.INFINITE
Expand Down Expand Up @@ -494,9 +495,14 @@ func (dbp *Process) waitForDebugEvent(flags waitForDebugEventFlags) (threadID, e
case _RIP_EVENT:
break
case _EXCEPTION_DEBUG_EVENT:
tid := int(debugEvent.ThreadId)
dbp.os.breakThread = tid
return tid, 0, nil
exception := (*_EXCEPTION_DEBUG_INFO)(unionPtr)
if code := exception.ExceptionRecord.ExceptionCode; code == _EXCEPTION_BREAKPOINT || code == _EXCEPTION_SINGLE_STEP {
tid := int(debugEvent.ThreadId)
dbp.os.breakThread = tid
return tid, 0, nil
} else {
continueStatus = _DBG_EXCEPTION_NOT_HANDLED
}
case _EXIT_PROCESS_DEBUG_EVENT:
debugInfo := (*_EXIT_PROCESS_DEBUG_INFO)(unionPtr)
exitCode = int(debugInfo.ExitCode)
Expand All @@ -506,7 +512,7 @@ func (dbp *Process) waitForDebugEvent(flags waitForDebugEventFlags) (threadID, e
}

// .. and then continue unless we received an event that indicated we should break into debugger.
err = _ContinueDebugEvent(debugEvent.ProcessId, debugEvent.ThreadId, _DBG_CONTINUE)
err = _ContinueDebugEvent(debugEvent.ProcessId, debugEvent.ThreadId, continueStatus)
if err != nil {
return 0, 0, err
}
Expand Down
19 changes: 19 additions & 0 deletions proc/syscall_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,20 @@ type _LOAD_DLL_DEBUG_INFO struct {
Unicode uint16
}

type _EXCEPTION_DEBUG_INFO struct {
ExceptionRecord _EXCEPTION_RECORD
FirstChance uint32
}

type _EXCEPTION_RECORD struct {
ExceptionCode uint32
ExceptionFlags uint32
ExceptionRecord *_EXCEPTION_RECORD
ExceptionAddress uintptr
NumberParameters uint32
ExceptionInformation [_EXCEPTION_MAXIMUM_PARAMETERS]uintptr
}

const (
_ThreadBasicInformation = 0

Expand All @@ -72,6 +86,11 @@ const (

// DEBUG_ONLY_THIS_PROCESS tracks https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx
_DEBUG_ONLY_THIS_PROCESS = 0x00000002

_EXCEPTION_BREAKPOINT = 0x80000003
_EXCEPTION_SINGLE_STEP = 0x80000004

_EXCEPTION_MAXIMUM_PARAMETERS = 15
)

func _NT_SUCCESS(x _NTSTATUS) bool {
Expand Down

0 comments on commit 8ef7d9e

Please sign in to comment.