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
This commit is contained in:
parent
25765063fc
commit
2c0e31160d
@ -321,7 +321,7 @@ func (p *Process) Connect(conn net.Conn, path string, pid int) error {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
bp, err := p.SetBreakpoint(panicpc, proc.UserBreakpoint, nil)
|
bp, err := p.SetBreakpoint(panicpc, proc.UserBreakpoint, nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
bp.Name = "unrecovered-panic"
|
bp.Name = proc.UnrecoveredPanic
|
||||||
bp.Variables = []string{"runtime.curg._panic.arg"}
|
bp.Variables = []string{"runtime.curg._panic.arg"}
|
||||||
bp.ID = -1
|
bp.ID = -1
|
||||||
p.breakpointIDCounter--
|
p.breakpointIDCounter--
|
||||||
@ -631,7 +631,22 @@ continueLoop:
|
|||||||
|
|
||||||
for _, thread := range p.threads {
|
for _, thread := range p.threads {
|
||||||
if thread.strID == threadID {
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,7 +408,7 @@ func initializeDebugProcess(dbp *Process, path string) (*Process, error) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
bp, err := dbp.SetBreakpoint(panicpc, proc.UserBreakpoint, nil)
|
bp, err := dbp.SetBreakpoint(panicpc, proc.UserBreakpoint, nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
bp.Name = "unrecovered-panic"
|
bp.Name = proc.UnrecoveredPanic
|
||||||
bp.Variables = []string{"runtime.curg._panic.arg"}
|
bp.Variables = []string{"runtime.curg._panic.arg"}
|
||||||
bp.ID = -1
|
bp.ID = -1
|
||||||
dbp.breakpointIDCounter--
|
dbp.breakpointIDCounter--
|
||||||
|
@ -19,6 +19,8 @@ type functionDebugInfo struct {
|
|||||||
var NotExecutableErr = errors.New("not an executable file")
|
var NotExecutableErr = errors.New("not an executable file")
|
||||||
var NotRecordedErr = errors.New("not a recording")
|
var NotRecordedErr = errors.New("not a recording")
|
||||||
|
|
||||||
|
const UnrecoveredPanic = "unrecovered-panic"
|
||||||
|
|
||||||
// ProcessExitedError indicates that the process has exited and contains both
|
// ProcessExitedError indicates that the process has exited and contains both
|
||||||
// process id and exit status.
|
// process id and exit status.
|
||||||
type ProcessExitedError struct {
|
type ProcessExitedError struct {
|
||||||
@ -169,6 +171,9 @@ func Continue(dbp Process) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if curbp.Name == UnrecoveredPanic {
|
||||||
|
dbp.ClearInternalBreakpoints()
|
||||||
|
}
|
||||||
return conditionErrors(threads)
|
return conditionErrors(threads)
|
||||||
default:
|
default:
|
||||||
// not a manual stop, not on runtime.Breakpoint, not on a breakpoint, just repeat
|
// not a manual stop, not on runtime.Breakpoint, not on a breakpoint, just repeat
|
||||||
|
@ -1871,7 +1871,7 @@ func TestPanicBreakpoint(t *testing.T) {
|
|||||||
withTestProcess("panic", t, func(p proc.Process, fixture protest.Fixture) {
|
withTestProcess("panic", t, func(p proc.Process, fixture protest.Fixture) {
|
||||||
assertNoError(proc.Continue(p), t, "Continue()")
|
assertNoError(proc.Continue(p), t, "Continue()")
|
||||||
bp, _, _ := p.CurrentThread().Breakpoint()
|
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)
|
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) {
|
expectSuccess := func(p proc.Process, fixture protest.Fixture) {
|
||||||
err := proc.Continue(p)
|
err := proc.Continue(p)
|
||||||
bp, _, _ := p.CurrentThread().Breakpoint()
|
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)
|
t.Fatalf("testing args failed on unrecovered-panic breakpoint: %v", bp)
|
||||||
}
|
}
|
||||||
exit, exited := err.(proc.ProcessExitedError)
|
exit, exited := err.(proc.ProcessExitedError)
|
||||||
@ -1897,7 +1897,7 @@ func TestCmdLineArgs(t *testing.T) {
|
|||||||
expectPanic := func(p proc.Process, fixture protest.Fixture) {
|
expectPanic := func(p proc.Process, fixture protest.Fixture) {
|
||||||
proc.Continue(p)
|
proc.Continue(p)
|
||||||
bp, _, _ := p.CurrentThread().Breakpoint()
|
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)
|
t.Fatalf("not on unrecovered-panic breakpoint: %v", bp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2283,7 +2283,7 @@ func TestStepConcurrentDirect(t *testing.T) {
|
|||||||
assertNoError(err, t, "ClearBreakpoint()")
|
assertNoError(err, t, "ClearBreakpoint()")
|
||||||
|
|
||||||
for _, b := range p.Breakpoints() {
|
for _, b := range p.Breakpoints() {
|
||||||
if b.Name == "unrecovered-panic" {
|
if b.Name == proc.UnrecoveredPanic {
|
||||||
_, err := p.ClearBreakpoint(b.Addr)
|
_, err := p.ClearBreakpoint(b.Addr)
|
||||||
assertNoError(err, t, "ClearBreakpoint(unrecovered-panic)")
|
assertNoError(err, t, "ClearBreakpoint(unrecovered-panic)")
|
||||||
break
|
break
|
||||||
@ -2354,7 +2354,7 @@ func TestStepConcurrentPtr(t *testing.T) {
|
|||||||
assertNoError(err, t, "SetBreakpoint()")
|
assertNoError(err, t, "SetBreakpoint()")
|
||||||
|
|
||||||
for _, b := range p.Breakpoints() {
|
for _, b := range p.Breakpoints() {
|
||||||
if b.Name == "unrecovered-panic" {
|
if b.Name == proc.UnrecoveredPanic {
|
||||||
_, err := p.ClearBreakpoint(b.Addr)
|
_, err := p.ClearBreakpoint(b.Addr)
|
||||||
assertNoError(err, t, "ClearBreakpoint(unrecovered-panic)")
|
assertNoError(err, t, "ClearBreakpoint(unrecovered-panic)")
|
||||||
break
|
break
|
||||||
|
@ -671,11 +671,18 @@ func restart(t *Term, ctx callContext, args string) error {
|
|||||||
return nil
|
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 {
|
func cont(t *Term, ctx callContext, args string) error {
|
||||||
stateChan := t.client.Continue()
|
stateChan := t.client.Continue()
|
||||||
var state *api.DebuggerState
|
var state *api.DebuggerState
|
||||||
for state = range stateChan {
|
for state = range stateChan {
|
||||||
if state.Err != nil {
|
if state.Err != nil {
|
||||||
|
printfileNoState(t)
|
||||||
return state.Err
|
return state.Err
|
||||||
}
|
}
|
||||||
printcontext(t, state)
|
printcontext(t, state)
|
||||||
@ -694,6 +701,7 @@ func continueUntilCompleteNext(t *Term, state *api.DebuggerState, op string) err
|
|||||||
var state *api.DebuggerState
|
var state *api.DebuggerState
|
||||||
for state = range stateChan {
|
for state = range stateChan {
|
||||||
if state.Err != nil {
|
if state.Err != nil {
|
||||||
|
printfileNoState(t)
|
||||||
return state.Err
|
return state.Err
|
||||||
}
|
}
|
||||||
printcontext(t, state)
|
printcontext(t, state)
|
||||||
@ -728,6 +736,7 @@ func step(t *Term, ctx callContext, args string) error {
|
|||||||
}
|
}
|
||||||
state, err := t.client.Step()
|
state, err := t.client.Step()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
printfileNoState(t)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
printcontext(t, state)
|
printcontext(t, state)
|
||||||
@ -740,6 +749,7 @@ func stepInstruction(t *Term, ctx callContext, args string) error {
|
|||||||
}
|
}
|
||||||
state, err := t.client.StepInstruction()
|
state, err := t.client.StepInstruction()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
printfileNoState(t)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
printcontext(t, state)
|
printcontext(t, state)
|
||||||
@ -753,6 +763,7 @@ func next(t *Term, ctx callContext, args string) error {
|
|||||||
}
|
}
|
||||||
state, err := t.client.Next()
|
state, err := t.client.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
printfileNoState(t)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
printcontext(t, state)
|
printcontext(t, state)
|
||||||
@ -765,6 +776,7 @@ func stepout(t *Term, ctx callContext, args string) error {
|
|||||||
}
|
}
|
||||||
state, err := t.client.StepOut()
|
state, err := t.client.StepOut()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
printfileNoState(t)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
printcontext(t, state)
|
printcontext(t, state)
|
||||||
|
Loading…
Reference in New Issue
Block a user