From 2c0e31160de8cba2a4351dcf39486d05313b4da1 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Wed, 20 Sep 2017 14:19:59 +0200 Subject: [PATCH] proc/gdbserial: return error if stopped with a sginal On macOS we can also stop when we receive a signal, propagate this reason upwards to the client. Also clear internal breakpoints after an unrecovered-panic since they can not be reached anymore. Fixes #872 --- pkg/proc/gdbserial/gdbserver.go | 19 +++++++++++++++++-- pkg/proc/native/proc.go | 2 +- pkg/proc/proc.go | 5 +++++ pkg/proc/proc_test.go | 10 +++++----- pkg/terminal/command.go | 12 ++++++++++++ 5 files changed, 40 insertions(+), 8 deletions(-) diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index 6cda348e..182aaf8b 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -321,7 +321,7 @@ func (p *Process) Connect(conn net.Conn, path string, pid int) error { if err == nil { bp, err := p.SetBreakpoint(panicpc, proc.UserBreakpoint, nil) if err == nil { - bp.Name = "unrecovered-panic" + bp.Name = proc.UnrecoveredPanic bp.Variables = []string{"runtime.curg._panic.arg"} bp.ID = -1 p.breakpointIDCounter-- @@ -631,7 +631,22 @@ continueLoop: for _, thread := range p.threads { if thread.strID == threadID { - return thread, nil + var err error = nil + switch sig { + case 0x91: + err = errors.New("bad access") + case 0x92: + err = errors.New("bad instruction") + case 0x93: + err = errors.New("arithmetic exception") + case 0x94: + err = errors.New("emulation exception") + case 0x95: + err = errors.New("software exception") + case 0x96: + err = errors.New("breakpoint exception") + } + return thread, err } } diff --git a/pkg/proc/native/proc.go b/pkg/proc/native/proc.go index 482abbb0..a7850fd7 100644 --- a/pkg/proc/native/proc.go +++ b/pkg/proc/native/proc.go @@ -408,7 +408,7 @@ func initializeDebugProcess(dbp *Process, path string) (*Process, error) { if err == nil { bp, err := dbp.SetBreakpoint(panicpc, proc.UserBreakpoint, nil) if err == nil { - bp.Name = "unrecovered-panic" + bp.Name = proc.UnrecoveredPanic bp.Variables = []string{"runtime.curg._panic.arg"} bp.ID = -1 dbp.breakpointIDCounter-- diff --git a/pkg/proc/proc.go b/pkg/proc/proc.go index 0dc590c5..b1897635 100644 --- a/pkg/proc/proc.go +++ b/pkg/proc/proc.go @@ -19,6 +19,8 @@ type functionDebugInfo struct { var NotExecutableErr = errors.New("not an executable file") var NotRecordedErr = errors.New("not a recording") +const UnrecoveredPanic = "unrecovered-panic" + // ProcessExitedError indicates that the process has exited and contains both // process id and exit status. type ProcessExitedError struct { @@ -169,6 +171,9 @@ func Continue(dbp Process) error { return err } } + if curbp.Name == UnrecoveredPanic { + dbp.ClearInternalBreakpoints() + } return conditionErrors(threads) default: // not a manual stop, not on runtime.Breakpoint, not on a breakpoint, just repeat diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go index 10977da5..7414f8dc 100644 --- a/pkg/proc/proc_test.go +++ b/pkg/proc/proc_test.go @@ -1871,7 +1871,7 @@ func TestPanicBreakpoint(t *testing.T) { withTestProcess("panic", t, func(p proc.Process, fixture protest.Fixture) { assertNoError(proc.Continue(p), t, "Continue()") bp, _, _ := p.CurrentThread().Breakpoint() - if bp == nil || bp.Name != "unrecovered-panic" { + if bp == nil || bp.Name != proc.UnrecoveredPanic { t.Fatalf("not on unrecovered-panic breakpoint: %v", bp) } }) @@ -1881,7 +1881,7 @@ func TestCmdLineArgs(t *testing.T) { expectSuccess := func(p proc.Process, fixture protest.Fixture) { err := proc.Continue(p) bp, _, _ := p.CurrentThread().Breakpoint() - if bp != nil && bp.Name == "unrecovered-panic" { + if bp != nil && bp.Name == proc.UnrecoveredPanic { t.Fatalf("testing args failed on unrecovered-panic breakpoint: %v", bp) } exit, exited := err.(proc.ProcessExitedError) @@ -1897,7 +1897,7 @@ func TestCmdLineArgs(t *testing.T) { expectPanic := func(p proc.Process, fixture protest.Fixture) { proc.Continue(p) bp, _, _ := p.CurrentThread().Breakpoint() - if bp == nil || bp.Name != "unrecovered-panic" { + if bp == nil || bp.Name != proc.UnrecoveredPanic { t.Fatalf("not on unrecovered-panic breakpoint: %v", bp) } } @@ -2283,7 +2283,7 @@ func TestStepConcurrentDirect(t *testing.T) { assertNoError(err, t, "ClearBreakpoint()") for _, b := range p.Breakpoints() { - if b.Name == "unrecovered-panic" { + if b.Name == proc.UnrecoveredPanic { _, err := p.ClearBreakpoint(b.Addr) assertNoError(err, t, "ClearBreakpoint(unrecovered-panic)") break @@ -2354,7 +2354,7 @@ func TestStepConcurrentPtr(t *testing.T) { assertNoError(err, t, "SetBreakpoint()") for _, b := range p.Breakpoints() { - if b.Name == "unrecovered-panic" { + if b.Name == proc.UnrecoveredPanic { _, err := p.ClearBreakpoint(b.Addr) assertNoError(err, t, "ClearBreakpoint(unrecovered-panic)") break diff --git a/pkg/terminal/command.go b/pkg/terminal/command.go index a09d2ab1..48b87ea7 100644 --- a/pkg/terminal/command.go +++ b/pkg/terminal/command.go @@ -671,11 +671,18 @@ func restart(t *Term, ctx callContext, args string) error { return nil } +func printfileNoState(t *Term) { + if state, _ := t.client.GetState(); state != nil && state.CurrentThread != nil { + printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true) + } +} + func cont(t *Term, ctx callContext, args string) error { stateChan := t.client.Continue() var state *api.DebuggerState for state = range stateChan { if state.Err != nil { + printfileNoState(t) return state.Err } printcontext(t, state) @@ -694,6 +701,7 @@ func continueUntilCompleteNext(t *Term, state *api.DebuggerState, op string) err var state *api.DebuggerState for state = range stateChan { if state.Err != nil { + printfileNoState(t) return state.Err } printcontext(t, state) @@ -728,6 +736,7 @@ func step(t *Term, ctx callContext, args string) error { } state, err := t.client.Step() if err != nil { + printfileNoState(t) return err } printcontext(t, state) @@ -740,6 +749,7 @@ func stepInstruction(t *Term, ctx callContext, args string) error { } state, err := t.client.StepInstruction() if err != nil { + printfileNoState(t) return err } printcontext(t, state) @@ -753,6 +763,7 @@ func next(t *Term, ctx callContext, args string) error { } state, err := t.client.Next() if err != nil { + printfileNoState(t) return err } printcontext(t, state) @@ -765,6 +776,7 @@ func stepout(t *Term, ctx callContext, args string) error { } state, err := t.client.StepOut() if err != nil { + printfileNoState(t) return err } printcontext(t, state) -- GitLab