debug: add DeleteBreakpoints function
DeleteBreakpoints accepts a slice of addresses, and removes any breakpoints
set at those addresses.
Adds a test where some breakpoints are set and deleted in the program
being debugged, and we check the program stops at the expected place.
Change-Id: I4ea4718e21e51587e48bd2eb57033ca774004e1a
Reviewed-on: https://go-review.googlesource.com/10079
Reviewed-by: Rob Pike <r@golang.org>
diff --git a/ogle/demo/ogler/ogler_test.go b/ogle/demo/ogler/ogler_test.go
index 65483ee..7c5faa3 100644
--- a/ogle/demo/ogler/ogler_test.go
+++ b/ogle/demo/ogler/ogler_test.go
@@ -189,4 +189,38 @@
log.Fatalf("Didn't get %s = %s\n", v, e)
}
}
+
+ // Remove the breakpoint at main.foo, set a breakpoint at main.f1 and main.f2,
+ // then delete the breakpoint at main.f1. Resume, then check we stopped at
+ // main.f2.
+ err = prog.DeleteBreakpoints(pcs)
+ if err != nil {
+ log.Fatalf("DeleteBreakpoints: %v", err)
+ }
+ pcs1, err := prog.Breakpoint("re:main.f1")
+ if err != nil {
+ log.Fatalf("Breakpoint: %v", err)
+ }
+ pcs2, err := prog.Breakpoint("re:main.f2")
+ if err != nil {
+ log.Fatalf("Breakpoint: %v", err)
+ }
+ err = prog.DeleteBreakpoints(pcs1)
+ if err != nil {
+ log.Fatalf("DeleteBreakpoints: %v", err)
+ }
+ status, err := prog.Resume()
+ if err != nil {
+ log.Fatalf("Resume: %v", err)
+ }
+ ok := false
+ for _, pc := range pcs2 {
+ if status.PC == pc {
+ ok = true
+ break
+ }
+ }
+ if !ok {
+ t.Errorf("Stopped at %X expected one of %X.", status.PC, pcs2)
+ }
}
diff --git a/ogle/demo/tracee/main.go b/ogle/demo/tracee/main.go
index 9d4a36c..a9cf90d 100644
--- a/ogle/demo/tracee/main.go
+++ b/ogle/demo/tracee/main.go
@@ -82,6 +82,16 @@
fmt.Println(Z_slice, Z_slice_2, Z_slice_nil)
fmt.Println(Z_string, Z_struct)
fmt.Println(Z_unsafe_pointer, Z_unsafe_pointer_nil)
+ f1()
+ f2()
+}
+
+func f1() {
+ fmt.Println()
+}
+
+func f2() {
+ fmt.Println()
}
func bar() {
diff --git a/ogle/program/client/client.go b/ogle/program/client/client.go
index b0d547a..c84c49c 100644
--- a/ogle/program/client/client.go
+++ b/ogle/program/client/client.go
@@ -203,8 +203,10 @@
return resp.PCs, err
}
-func (p *Program) DeleteBreakpoint(address string) error {
- panic("unimplemented")
+func (p *Program) DeleteBreakpoints(pcs []uint64) error {
+ req := proxyrpc.DeleteBreakpointsRequest{PCs: pcs}
+ var resp proxyrpc.DeleteBreakpointsResponse
+ return p.client.Call("Server.DeleteBreakpoints", &req, &resp)
}
func (p *Program) Eval(expr string) ([]string, error) {
diff --git a/ogle/program/program.go b/ogle/program/program.go
index 4481413..b633e18 100644
--- a/ogle/program/program.go
+++ b/ogle/program/program.go
@@ -62,9 +62,9 @@
// expression to match a set of symbols.
Breakpoint(address string) (PCs []uint64, err error)
- // DeleteBreakpoint removes the breakpoint at the specified
- // address. TODO: Probably the wrong interface.
- DeleteBreakpoint(address string) error
+ // DeleteBreakpoints removes the breakpoints at the specified addresses.
+ // Addresses where no breakpoint is set are ignored.
+ DeleteBreakpoints(pcs []uint64) error
// Eval evaluates the expression (typically an address) and returns
// its string representation(s). Multivalued expressions such as
diff --git a/ogle/program/proxyrpc/proxyrpc.go b/ogle/program/proxyrpc/proxyrpc.go
index fba3ec1..eef2864 100644
--- a/ogle/program/proxyrpc/proxyrpc.go
+++ b/ogle/program/proxyrpc/proxyrpc.go
@@ -73,6 +73,13 @@
PCs []uint64
}
+type DeleteBreakpointsRequest struct {
+ PCs []uint64
+}
+
+type DeleteBreakpointsResponse struct {
+}
+
type EvalRequest struct {
Expr string
}
diff --git a/ogle/program/server/server.go b/ogle/program/server/server.go
index 1717094..296e20e 100644
--- a/ogle/program/server/server.go
+++ b/ogle/program/server/server.go
@@ -148,6 +148,8 @@
switch req := c.req.(type) {
case *proxyrpc.BreakpointRequest:
c.errc <- s.handleBreakpoint(req, c.resp.(*proxyrpc.BreakpointResponse))
+ case *proxyrpc.DeleteBreakpointsRequest:
+ c.errc <- s.handleDeleteBreakpoints(req, c.resp.(*proxyrpc.DeleteBreakpointsResponse))
case *proxyrpc.CloseRequest:
c.errc <- s.handleClose(req, c.resp.(*proxyrpc.CloseResponse))
case *proxyrpc.EvalRequest:
@@ -418,6 +420,17 @@
return nil
}
+func (s *Server) DeleteBreakpoints(req *proxyrpc.DeleteBreakpointsRequest, resp *proxyrpc.DeleteBreakpointsResponse) error {
+ return s.call(s.breakpointc, req, resp)
+}
+
+func (s *Server) handleDeleteBreakpoints(req *proxyrpc.DeleteBreakpointsRequest, resp *proxyrpc.DeleteBreakpointsResponse) error {
+ for _, pc := range req.PCs {
+ delete(s.breakpoints, pc)
+ }
+ return nil
+}
+
func (s *Server) setBreakpoints() error {
for pc := range s.breakpoints {
err := s.ptracePoke(s.stoppedPid, uintptr(pc), s.arch.BreakpointInstr[:s.arch.BreakpointSize])