mirror of
https://github.com/go-delve/delve.git
synced 2025-10-31 02:36:18 +08:00
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:
committed by
Derek Parker
parent
89d2167c31
commit
dcc1030d18
@ -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
|
||||||
|
|||||||
@ -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")
|
||||||
|
|||||||
Reference in New Issue
Block a user