Ensure breakpoint is set only once
This commit is contained in:
parent
798fdd9de0
commit
03fab9c26e
@ -20,6 +20,13 @@ type DebuggedProcess struct {
|
|||||||
Executable *elf.File
|
Executable *elf.File
|
||||||
Symbols []elf.Symbol
|
Symbols []elf.Symbol
|
||||||
GoSymTable *gosym.Table
|
GoSymTable *gosym.Table
|
||||||
|
BreakPoints map[string]*BreakPoint
|
||||||
|
}
|
||||||
|
|
||||||
|
type BreakPoint struct {
|
||||||
|
FunctionName string
|
||||||
|
Line int
|
||||||
|
Addr uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a new DebuggedProcess struct with sensible defaults.
|
// Returns a new DebuggedProcess struct with sensible defaults.
|
||||||
@ -44,6 +51,7 @@ func NewDebugProcess(pid int) (*DebuggedProcess, error) {
|
|||||||
Regs: &syscall.PtraceRegs{},
|
Regs: &syscall.PtraceRegs{},
|
||||||
Process: proc,
|
Process: proc,
|
||||||
ProcessState: ps,
|
ProcessState: ps,
|
||||||
|
BreakPoints: make(map[string]*BreakPoint),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = debuggedProc.LoadInformation()
|
err = debuggedProc.LoadInformation()
|
||||||
@ -79,19 +87,32 @@ func (dbp *DebuggedProcess) Registers() (*syscall.PtraceRegs, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sets a breakpoint in the running process.
|
// Sets a breakpoint in the running process.
|
||||||
func (dbp *DebuggedProcess) Break(fname string) error {
|
func (dbp *DebuggedProcess) Break(fname string) (*BreakPoint, error) {
|
||||||
var (
|
var (
|
||||||
breakpoint = []byte{'0', 'x', 'C', 'C'}
|
int3 = []byte{'0', 'x', 'C', 'C'}
|
||||||
fn = dbp.GoSymTable.LookupFunc(fname)
|
fn = dbp.GoSymTable.LookupFunc(fname)
|
||||||
addr = uintptr(fn.LineTable.PC)
|
addr = uintptr(fn.LineTable.PC)
|
||||||
)
|
)
|
||||||
|
|
||||||
_, err := syscall.PtracePokeData(dbp.Pid, addr, breakpoint)
|
_, ok := dbp.BreakPoints[fname]
|
||||||
if err != nil {
|
if ok {
|
||||||
return err
|
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.
|
// Steps through process.
|
||||||
|
|||||||
@ -110,7 +110,7 @@ func TestBreakPoint(t *testing.T) {
|
|||||||
t.Fatal("NewDebugProcess():", err)
|
t.Fatal("NewDebugProcess():", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = p.Break("main.sleepytime")
|
_, err = p.Break("main.sleepytime")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("Break():", err)
|
t.Fatal("Break():", err)
|
||||||
}
|
}
|
||||||
@ -135,3 +135,26 @@ func TestBreakPoint(t *testing.T) {
|
|||||||
|
|
||||||
cmd.Process.Kill()
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user