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:
		 Alessandro Arzilli
					Alessandro Arzilli
				
			
				
					committed by
					
						 Derek Parker
						Derek Parker
					
				
			
			
				
	
			
			
			 Derek Parker
						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