gdbserial: propagate signals to target while stepping (#1624)

Propagate signals when stepping because debugserver will report them,
from the issue:

2019-07-11T16:31:25+02:00 debug layer=gdbconn <- $z0,105525d,1#c9
2019-07-11T16:31:25+02:00 debug layer=gdbconn -> $OK#00
2019-07-11T16:31:25+02:00 debug layer=gdbconn <- $vCont;s:c41c3#50
2019-07-11T16:31:25+02:00 debug layer=gdbconn -> $T1cthread:c41c3;threads:c41c3,c41d7,c41d8,c41d9,c41da;thread-pcs:105525d,7fffc464bf46,7fffc464bbf2,7fffc464bbf2,7fffc46...
2019-07-11T16:31:25+02:00 debug layer=gdbconn <- $Z0,105525d,1#a9
2019-07-11T16:31:25+02:00 debug layer=gdbconn -> $OK#00

in this case we request a single step on thread c41c3 but debugserver
reports instead a signal (in this case SIGWINCH).

Fixes #1610
This commit is contained in:
Alessandro Arzilli
2019-07-23 23:42:21 +02:00
committed by Derek Parker
parent 89d2167c31
commit dcc1030d18
2 changed files with 52 additions and 14 deletions

View File

@ -610,8 +610,16 @@ func (p *Process) SelectedGoroutine() *proc.G {
const ( const (
interruptSignal = 0x2 interruptSignal = 0x2
breakpointSignal = 0x5 breakpointSignal = 0x5
faultSignal = 0xb
childSignal = 0x11 childSignal = 0x11
stopSignal = 0x13 stopSignal = 0x13
debugServerTargetExcBadAccess = 0x91
debugServerTargetExcBadInstruction = 0x92
debugServerTargetExcArithmetic = 0x93
debugServerTargetExcEmulation = 0x94
debugServerTargetExcSoftware = 0x95
debugServerTargetExcBreakpoint = 0x96
) )
// ContinueOnce will continue execution of the process until // ContinueOnce will continue execution of the process until
@ -677,7 +685,8 @@ continueLoop:
// The following are fake BSD-style signals sent by debugserver // The following are fake BSD-style signals sent by debugserver
// Unfortunately debugserver can not convert them into signals for the // Unfortunately debugserver can not convert them into signals for the
// process so we must stop here. // process so we must stop here.
case 0x91, 0x92, 0x93, 0x94, 0x95, 0x96: /* TARGET_EXC_BAD_ACCESS */ case debugServerTargetExcBadAccess, debugServerTargetExcBadInstruction, debugServerTargetExcArithmetic, debugServerTargetExcEmulation, debugServerTargetExcSoftware, debugServerTargetExcBreakpoint:
break continueLoop break continueLoop
// Signal 0 is returned by rr when it reaches the start of the process // Signal 0 is returned by rr when it reaches the start of the process
@ -1274,8 +1283,7 @@ func (t *Thread) stepInstruction(tu *threadUpdater) error {
} }
defer t.p.conn.setBreakpoint(pc) defer t.p.conn.setBreakpoint(pc)
} }
_, _, err := t.p.conn.step(t.strID, tu) return t.p.conn.step(t.strID, tu, false)
return err
} }
// StepInstruction will step exactly 1 CPU instruction. // StepInstruction will step exactly 1 CPU instruction.
@ -1485,7 +1493,7 @@ func (t *Thread) reloadGAtPC() error {
} }
}() }()
_, _, err = t.p.conn.step(t.strID, nil) err = t.p.conn.step(t.strID, nil, true)
if err != nil { if err != nil {
if err == threadBlockedError { if err == threadBlockedError {
t.regs.tls = 0 t.regs.tls = 0
@ -1538,7 +1546,7 @@ func (t *Thread) reloadGAlloc() error {
} }
}() }()
_, _, err = t.p.conn.step(t.strID, nil) err = t.p.conn.step(t.strID, nil, true)
if err != nil { if err != nil {
if err == threadBlockedError { if err == threadBlockedError {
t.regs.tls = 0 t.regs.tls = 0

View File

@ -575,21 +575,51 @@ func (conn *gdbConn) resume(sig uint8, tu *threadUpdater) (string, uint8, error)
} }
// step executes a 'vCont' command on the specified thread with 's' action. // step executes a 'vCont' command on the specified thread with 's' action.
func (conn *gdbConn) step(threadID string, tu *threadUpdater) (string, uint8, error) { func (conn *gdbConn) step(threadID string, tu *threadUpdater, ignoreFaultSignal bool) error {
if conn.direction == proc.Forward { if conn.direction != proc.Forward {
conn.outbuf.Reset()
fmt.Fprintf(&conn.outbuf, "$vCont;s:%s", threadID)
} else {
if err := conn.selectThread('c', threadID, "step"); err != nil { if err := conn.selectThread('c', threadID, "step"); err != nil {
return "", 0, err return err
} }
conn.outbuf.Reset() conn.outbuf.Reset()
fmt.Fprint(&conn.outbuf, "$bs") fmt.Fprint(&conn.outbuf, "$bs")
if err := conn.send(conn.outbuf.Bytes()); err != nil {
return err
}
_, _, err := conn.waitForvContStop("singlestep", threadID, tu)
return err
} }
if err := conn.send(conn.outbuf.Bytes()); err != nil { var sig uint8 = 0
return "", 0, err for {
conn.outbuf.Reset()
if sig == 0 {
fmt.Fprintf(&conn.outbuf, "$vCont;s:%s", threadID)
} else {
fmt.Fprintf(&conn.outbuf, "$vCont;S%02x:%s", sig, threadID)
}
if err := conn.send(conn.outbuf.Bytes()); err != nil {
return err
}
var err error
_, sig, err = conn.waitForvContStop("singlestep", threadID, tu)
if err != nil {
return err
}
switch sig {
case faultSignal:
if ignoreFaultSignal { // we attempting to read the TLS, a fault here should be ignored
return nil
}
case interruptSignal, breakpointSignal, stopSignal:
return nil
case childSignal: // stop on debugserver but SIGCHLD on lldb-server/linux
if conn.isDebugserver {
return nil
}
case debugServerTargetExcBadAccess, debugServerTargetExcBadInstruction, debugServerTargetExcArithmetic, debugServerTargetExcEmulation, debugServerTargetExcSoftware, debugServerTargetExcBreakpoint:
return nil
}
// any other signal is propagated to the inferior
} }
return conn.waitForvContStop("singlestep", threadID, tu)
} }
var threadBlockedError = errors.New("thread blocked") var threadBlockedError = errors.New("thread blocked")