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])