mirror of
				https://github.com/go-delve/delve.git
				synced 2025-10-31 10:47:27 +08:00 
			
		
		
		
	Ensure breakpoint is set only once
This commit is contained in:
		| @ -20,6 +20,13 @@ type DebuggedProcess struct { | ||||
| 	Executable   *elf.File | ||||
| 	Symbols      []elf.Symbol | ||||
| 	GoSymTable   *gosym.Table | ||||
| 	BreakPoints  map[string]*BreakPoint | ||||
| } | ||||
|  | ||||
| type BreakPoint struct { | ||||
| 	FunctionName string | ||||
| 	Line         int | ||||
| 	Addr         uint64 | ||||
| } | ||||
|  | ||||
| // Returns a new DebuggedProcess struct with sensible defaults. | ||||
| @ -44,6 +51,7 @@ func NewDebugProcess(pid int) (*DebuggedProcess, error) { | ||||
| 		Regs:         &syscall.PtraceRegs{}, | ||||
| 		Process:      proc, | ||||
| 		ProcessState: ps, | ||||
| 		BreakPoints:  make(map[string]*BreakPoint), | ||||
| 	} | ||||
|  | ||||
| 	err = debuggedProc.LoadInformation() | ||||
| @ -79,19 +87,32 @@ func (dbp *DebuggedProcess) Registers() (*syscall.PtraceRegs, error) { | ||||
| } | ||||
|  | ||||
| // Sets a breakpoint in the running process. | ||||
| func (dbp *DebuggedProcess) Break(fname string) error { | ||||
| func (dbp *DebuggedProcess) Break(fname string) (*BreakPoint, error) { | ||||
| 	var ( | ||||
| 		breakpoint = []byte{'0', 'x', 'C', 'C'} | ||||
| 		fn         = dbp.GoSymTable.LookupFunc(fname) | ||||
| 		addr       = uintptr(fn.LineTable.PC) | ||||
| 		int3 = []byte{'0', 'x', 'C', 'C'} | ||||
| 		fn   = dbp.GoSymTable.LookupFunc(fname) | ||||
| 		addr = uintptr(fn.LineTable.PC) | ||||
| 	) | ||||
|  | ||||
| 	_, err := syscall.PtracePokeData(dbp.Pid, addr, breakpoint) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	_, ok := dbp.BreakPoints[fname] | ||||
| 	if ok { | ||||
| 		return nil, fmt.Errorf("Breakpoint already set") | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| 	_, err := syscall.PtracePokeData(dbp.Pid, addr, int3) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	breakpoint := &BreakPoint{ | ||||
| 		FunctionName: fn.Name, | ||||
| 		Line:         fn.LineTable.Line, | ||||
| 		Addr:         fn.LineTable.PC, | ||||
| 	} | ||||
|  | ||||
| 	dbp.BreakPoints[fname] = breakpoint | ||||
|  | ||||
| 	return breakpoint, nil | ||||
| } | ||||
|  | ||||
| // Steps through process. | ||||
|  | ||||
| @ -110,7 +110,7 @@ func TestBreakPoint(t *testing.T) { | ||||
| 		t.Fatal("NewDebugProcess():", err) | ||||
| 	} | ||||
|  | ||||
| 	err = p.Break("main.sleepytime") | ||||
| 	_, err = p.Break("main.sleepytime") | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Break():", err) | ||||
| 	} | ||||
| @ -135,3 +135,26 @@ func TestBreakPoint(t *testing.T) { | ||||
|  | ||||
| 	cmd.Process.Kill() | ||||
| } | ||||
|  | ||||
| func TestBreakPointIsSetOnlyOnce(t *testing.T) { | ||||
| 	cmd, err := StartTestProcess("testprog") | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Starting test process:", err) | ||||
| 	} | ||||
|  | ||||
| 	pid := cmd.Process.Pid | ||||
| 	p, err := NewDebugProcess(pid) | ||||
| 	if err != nil { | ||||
| 		t.Fatal("NewDebugProcess():", err) | ||||
| 	} | ||||
|  | ||||
| 	_, err = p.Break("main.sleepytime") | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Break():", err) | ||||
| 	} | ||||
|  | ||||
| 	_, err = p.Break("main.sleepytime") | ||||
| 	if err == nil { | ||||
| 		t.Fatal("Should not be able to add breakpoint twice") | ||||
| 	} | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Derek Parker
					Derek Parker