mirror of
				https://github.com/go-delve/delve.git
				synced 2025-10-31 10:47:27 +08:00 
			
		
		
		
	Refactor: Use thread-locked goroutine for ptrace ops
Previously either the terminal client or the debugger service would either lock main goroutine to a thread or provide a locked goroutine to run _all_ DebuggedProcess functions in. This is unnecessary because only ptrace functions need to be run from the same thread that originated the PT_ATTACH request. Here we use a specific thread-locked goroutine to service any ptrace request. That goroutine is also responsible for the initial spawning / attaching of the process, since it must be responsible for the PT_ATTACH request.
This commit is contained in:
		| @ -21,7 +21,7 @@ import "fmt" | ||||
| // debug register `reg` with the address of the instruction | ||||
| // that we want to break at. There are only 4 debug registers | ||||
| // DR0-DR3. Debug register 7 is the control register. | ||||
| func setHardwareBreakpoint(reg, tid int, addr uint64) error { | ||||
| func (dbp *DebuggedProcess) setHardwareBreakpoint(reg, tid int, addr uint64) error { | ||||
| 	if reg < 0 || reg > 3 { | ||||
| 		return fmt.Errorf("invalid debug register value") | ||||
| 	} | ||||
| @ -32,10 +32,12 @@ func setHardwareBreakpoint(reg, tid int, addr uint64) error { | ||||
| 		drxmask   = uintptr((((1 << C.DR_CONTROL_SIZE) - 1) << uintptr(reg*C.DR_CONTROL_SIZE)) | (((1 << C.DR_ENABLE_SIZE) - 1) << uintptr(reg*C.DR_ENABLE_SIZE))) | ||||
| 		drxenable = uintptr(0x1) << uintptr(reg*C.DR_ENABLE_SIZE) | ||||
| 		drxctl    = uintptr(C.DR_RW_EXECUTE|C.DR_LEN_1) << uintptr(reg*C.DR_CONTROL_SIZE) | ||||
| 		dr7       uintptr | ||||
| 	) | ||||
|  | ||||
| 	// Get current state | ||||
| 	dr7, err := PtracePeekUser(tid, dr7off) | ||||
| 	var err error | ||||
| 	dbp.execPtraceFunc(func() { dr7, err = PtracePeekUser(tid, dr7off) }) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @ -43,12 +45,14 @@ func setHardwareBreakpoint(reg, tid int, addr uint64) error { | ||||
| 	// If addr == 0 we are expected to disable the breakpoint | ||||
| 	if addr == 0 { | ||||
| 		dr7 &= ^drxmask | ||||
| 		return PtracePokeUser(tid, dr7off, dr7) | ||||
| 		dbp.execPtraceFunc(func() { err = PtracePokeUser(tid, dr7off, dr7) }) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Set the debug register `reg` with the address of the | ||||
| 	// instruction we want to trigger a debug exception. | ||||
| 	if err := PtracePokeUser(tid, drxoff, uintptr(addr)); err != nil { | ||||
| 	dbp.execPtraceFunc(func() { err = PtracePokeUser(tid, drxoff, uintptr(addr)) }) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| @ -61,12 +65,13 @@ func setHardwareBreakpoint(reg, tid int, addr uint64) error { | ||||
| 	// instructs the cpu to raise a debug | ||||
| 	// exception when hitting the address of | ||||
| 	// an instruction stored in dr0-dr3. | ||||
| 	return PtracePokeUser(tid, dr7off, dr7) | ||||
| 	dbp.execPtraceFunc(func() { err = PtracePokeUser(tid, dr7off, dr7) }) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // Clears a hardware breakpoint. Essentially sets | ||||
| // the debug reg to 0 and clears the control register | ||||
| // flags for that reg. | ||||
| func clearHardwareBreakpoint(reg, tid int) error { | ||||
| 	return setHardwareBreakpoint(reg, tid, 0) | ||||
| func (dbp *DebuggedProcess) clearHardwareBreakpoint(reg, tid int) error { | ||||
| 	return dbp.setHardwareBreakpoint(reg, tid, 0) | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Derek Parker
					Derek Parker