func restart(client service.Client, args ...string) error { if err := client.Restart(); err != nil { return err } fmt.Println("Process restarted with PID", client.ProcessPid()) return nil }
func findLocationHelper(t *testing.T, c service.Client, loc string, shouldErr bool, count int, checkAddr uint64) []uint64 { locs, err := c.FindLocation(api.EvalScope{-1, 0}, loc) t.Logf("FindLocation(\"%s\") → %v\n", loc, locs) if shouldErr { if err == nil { t.Fatalf("Resolving location <%s> didn't return an error: %v", loc, locs) } } else { if err != nil { t.Fatalf("Error resolving location <%s>: %v", loc, err) } } if (count >= 0) && (len(locs) != count) { t.Fatalf("Wrong number of breakpoints returned for location <%s> (got %d, expected %d)", loc, len(locs), count) } if checkAddr != 0 && checkAddr != locs[0].PC { t.Fatalf("Wrong address returned for location <%s> (got %v, epected %v)", loc, locs[0].PC, checkAddr) } addrs := make([]uint64, len(locs)) for i := range locs { addrs[i] = locs[i].PC } return addrs }
func locals(client service.Client, scope api.EvalScope, filter string) ([]string, error) { locals, err := client.ListLocalVariables(scope) if err != nil { return nil, err } return filterVariables(locals, filter), nil }
func goroutine(client service.Client, args ...string) error { switch len(args) { case 0: return printscope(client) case 1: gid, err := strconv.Atoi(args[0]) if err != nil { return err } oldState, err := client.GetState() if err != nil { return err } newState, err := client.SwitchGoroutine(gid) if err != nil { return err } fmt.Printf("Switched from %d to %d (thread %d)\n", oldState.SelectedGoroutine.ID, gid, newState.CurrentThread.ID) return nil default: return scopePrefix(client, "goroutine", args...) } }
func breakpoints(client service.Client, args ...string) error { breakPoints, err := client.ListBreakpoints() if err != nil { return err } sort.Sort(ById(breakPoints)) for _, bp := range breakPoints { thing := "Breakpoint" if bp.Tracepoint { thing = "Tracepoint" } fmt.Printf("%s %d at %#v %s:%d\n", thing, bp.ID, bp.Addr, shortenFilePath(bp.File), bp.Line) var attrs []string if bp.Stacktrace > 0 { attrs = append(attrs, "-stack") attrs = append(attrs, strconv.Itoa(bp.Stacktrace)) } if bp.Goroutine { attrs = append(attrs, "-goroutine") } for i := range bp.Variables { attrs = append(attrs, bp.Variables[i]) } if len(attrs) > 0 { fmt.Printf("\t%s\n", strings.Join(attrs, " ")) } } return nil }
func vars(client service.Client, filter string) ([]string, error) { vars, err := client.ListPackageVariables(filter) if err != nil { return nil, err } return filterVariables(vars, filter), nil }
func setVar(client service.Client, scope api.EvalScope, args ...string) error { if len(args) != 2 { return fmt.Errorf("wrong number of arguments") } return client.SetVariable(scope, args[0], args[1]) }
func args(client service.Client, scope api.EvalScope, filter string) ([]string, error) { vars, err := client.ListFunctionArgs(scope) if err != nil { return nil, err } return filterVariables(vars, filter), nil }
func threads(client service.Client, args ...string) error { threads, err := client.ListThreads() if err != nil { return err } state, err := client.GetState() if err != nil { return err } sort.Sort(byThreadID(threads)) for _, th := range threads { prefix := " " if state.CurrentThread != nil && state.CurrentThread.ID == th.ID { prefix = "* " } if th.Function != nil { fmt.Printf("%sThread %d at %#v %s:%d %s\n", prefix, th.ID, th.PC, shortenFilePath(th.File), th.Line, th.Function.Name) } else { fmt.Printf("%sThread %s\n", prefix, formatThread(th)) } } return nil }
func handleExit(client service.Client, t *Term) (error, int) { fullHistoryFile, err := getConfigFilePath(historyFile) if err != nil { fmt.Println("Error saving history file:", err) } else { if f, err := os.OpenFile(fullHistoryFile, os.O_RDWR, 0666); err == nil { _, err := t.line.WriteHistory(f) if err != nil { fmt.Println("readline history error: ", err) } f.Close() } } kill := true if client.AttachedToExistingProcess() { answer, err := t.line.Prompt("Would you like to kill the process? [Y/n] ") if err != nil { return io.EOF, 2 } answer = strings.ToLower(strings.TrimSpace(answer)) kill = (answer != "n" && answer != "no") } err = client.Detach(kill) if err != nil { return err, 1 } return nil, 0 }
func stackCommand(client service.Client, args ...string) error { var err error goroutineid := -1 depth := 10 switch len(args) { case 0: // nothing to do case 2: goroutineid, err = strconv.Atoi(args[1]) if err != nil { return fmt.Errorf("Wrong argument: expected integer") } fallthrough case 1: depth, err = strconv.Atoi(args[0]) if err != nil { return fmt.Errorf("Wrong argument: expected integer") } default: return fmt.Errorf("Wrong number of arguments to stack") } stack, err := client.Stacktrace(goroutineid, depth) if err != nil { return err } printStack(stack, "") return nil }
func breakpoint(client service.Client, args ...string) error { if len(args) != 1 { return fmt.Errorf("argument must be either a function name or <file:line>") } requestedBp := &api.Breakpoint{} tokens := strings.Split(args[0], ":") switch { case len(tokens) == 1: requestedBp.FunctionName = args[0] case len(tokens) == 2: file := tokens[0] line, err := strconv.Atoi(tokens[1]) if err != nil { return err } requestedBp.File = file requestedBp.Line = line default: return fmt.Errorf("invalid line reference") } bp, err := client.CreateBreakpoint(requestedBp) if err != nil { return err } fmt.Printf("Breakpoint %d set at %#v for %s %s:%d\n", bp.ID, bp.Addr, bp.FunctionName, bp.File, bp.Line) return nil }
func thread(client service.Client, args ...string) error { if len(args) == 0 { return fmt.Errorf("you must specify a thread") } tid, err := strconv.Atoi(args[0]) if err != nil { return err } oldState, err := client.GetState() if err != nil { return err } newState, err := client.SwitchThread(tid) if err != nil { return err } oldThread := "<none>" newThread := "<none>" if oldState.CurrentThread != nil { oldThread = strconv.Itoa(oldState.CurrentThread.ID) } if newState.CurrentThread != nil { newThread = strconv.Itoa(newState.CurrentThread.ID) } fmt.Printf("Switched from %s to %s\n", oldThread, newThread) return nil }
func regs(client service.Client, args ...string) error { regs, err := client.ListRegisters() if err != nil { return err } fmt.Println(regs) return nil }
func next(client service.Client, args ...string) error { state, err := client.Next() if err != nil { return err } printcontext(state) return nil }
func printscope(client service.Client) error { state, err := client.GetState() if err != nil { return err } fmt.Printf("Thread %s\nGoroutine %s\n", formatThread(state.CurrentThread), formatGoroutine(state.SelectedGoroutine)) return nil }
func cont(client service.Client, args ...string) error { stateChan := client.Continue() for state := range stateChan { if state.Err != nil { return state.Err } printcontext(state) } return nil }
func goroutines(client service.Client, args ...string) error { gs, err := client.ListGoroutines() if err != nil { return err } fmt.Printf("[%d goroutines]\n", len(gs)) for _, g := range gs { fmt.Printf("Goroutine %s\n", formatGoroutine(g)) } return nil }
func printVar(client service.Client, scope api.EvalScope, args ...string) error { if len(args) == 0 { return fmt.Errorf("not enough arguments") } val, err := client.EvalVariable(scope, args[0]) if err != nil { return err } fmt.Println(val.Value) return nil }
func setBreakpoint(client service.Client, tracepoint bool, args ...string) error { if len(args) < 1 { return fmt.Errorf("address required, specify either a function name or <file:line>") } requestedBp := &api.Breakpoint{} tokens := strings.Split(args[0], ":") switch { case len(tokens) == 1: requestedBp.FunctionName = args[0] case len(tokens) == 2: file := tokens[0] line, err := strconv.Atoi(tokens[1]) if err != nil { return err } requestedBp.File = file requestedBp.Line = line default: return fmt.Errorf("invalid line reference") } for i := 1; i < len(args); i++ { switch args[i] { case "-stack": i++ n, err := strconv.Atoi(args[i]) if err != nil { return fmt.Errorf("argument of -stack must be a number") } requestedBp.Stacktrace = n case "-goroutine": requestedBp.Goroutine = true default: requestedBp.Variables = append(requestedBp.Variables, args[i]) } } requestedBp.Tracepoint = tracepoint bp, err := client.CreateBreakpoint(requestedBp) if err != nil { return err } thing := "Breakpoint" if tracepoint { thing = "Tracepoint" } fmt.Printf("%s %d set at %#v for %s %s:%d\n", thing, bp.ID, bp.Addr, bp.FunctionName, bp.File, bp.Line) return nil }
func breakpoints(client service.Client, args ...string) error { breakPoints, err := client.ListBreakpoints() if err != nil { return err } sort.Sort(ById(breakPoints)) for _, bp := range breakPoints { fmt.Printf("Breakpoint %d at %#v %s:%d\n", bp.ID, bp.Addr, bp.File, bp.Line) } return nil }
func clearAll(client service.Client, args ...string) error { breakPoints, err := client.ListBreakpoints() if err != nil { return err } for _, bp := range breakPoints { _, err := client.ClearBreakpoint(bp.ID) if err != nil { fmt.Printf("Couldn't delete breakpoint %d at %#v %s:%d: %s\n", bp.ID, bp.Addr, shortenFilePath(bp.File), bp.Line, err) } fmt.Printf("Breakpoint %d cleared at %#v for %s %s:%d\n", bp.ID, bp.Addr, bp.FunctionName, shortenFilePath(bp.File), bp.Line) } return nil }
func goroutines(client service.Client, args ...string) error { gs, err := client.ListGoroutines() if err != nil { return err } fmt.Printf("[%d goroutines]\n", len(gs)) for _, g := range gs { var fname string if g.Function != nil { fname = g.Function.Name } fmt.Printf("Goroutine %d - %s:%d %s (%#v)\n", g.ID, g.File, g.Line, fname, g.PC) } return nil }
func clear(client service.Client, args ...string) error { if len(args) == 0 { return fmt.Errorf("not enough arguments") } id, err := strconv.Atoi(args[0]) if err != nil { return err } bp, err := client.ClearBreakpoint(id) if err != nil { return err } fmt.Printf("Breakpoint %d cleared at %#v for %s %s:%d\n", bp.ID, bp.Addr, bp.FunctionName, shortenFilePath(bp.File), bp.Line) return nil }
func setBreakpoint(client service.Client, tracepoint bool, args ...string) error { if len(args) < 1 { return fmt.Errorf("address required, specify either a function name or <file:line>") } requestedBp := &api.Breakpoint{} for i := 1; i < len(args); i++ { switch args[i] { case "-stack": i++ n, err := strconv.Atoi(args[i]) if err != nil { return fmt.Errorf("argument of -stack must be a number") } requestedBp.Stacktrace = n case "-goroutine": requestedBp.Goroutine = true default: requestedBp.Variables = append(requestedBp.Variables, args[i]) } } requestedBp.Tracepoint = tracepoint locs, err := client.FindLocation(args[0]) if err != nil { return err } thing := "Breakpoint" if tracepoint { thing = "Tracepoint" } for _, loc := range locs { requestedBp.Addr = loc.PC bp, err := client.CreateBreakpoint(requestedBp) if err != nil { return err } fmt.Printf("%s %d set at %#v for %s %s:%d\n", thing, bp.ID, bp.Addr, bp.FunctionName, bp.File, bp.Line) } return nil }
func stackCommand(client service.Client, args ...string) error { var ( err error goroutineid = -1 ) depth, full, err := parseStackArgs(args) if err != nil { return err } stack, err := client.Stacktrace(goroutineid, depth, full) if err != nil { return err } printStack(stack, "") return nil }
func goroutines(client service.Client, args ...string) error { state, err := client.GetState() if err != nil { return err } gs, err := client.ListGoroutines() if err != nil { return err } fmt.Printf("[%d goroutines]\n", len(gs)) for _, g := range gs { prefix := " " if g.ID == state.SelectedGoroutine.ID { prefix = "* " } fmt.Printf("%sGoroutine %s\n", prefix, formatGoroutine(g)) } return nil }
func listCommand(client service.Client, args ...string) error { if len(args) == 0 { state, err := client.GetState() if err != nil { return err } printcontext(state) return nil } locs, err := client.FindLocation(api.EvalScope{-1, 0}, args[0]) if err != nil { return err } if len(locs) > 1 { return debugger.AmbiguousLocationError{Location: args[0], CandidatesLocation: locs} } printfile(locs[0].File, locs[0].Line, false) return nil }
func stackCommand(client service.Client, args ...string) error { var err error goroutineid := -1 depth := 10 switch len(args) { case 0: // nothing to do case 2: goroutineid, err = strconv.Atoi(args[1]) if err != nil { return fmt.Errorf("Wrong argument: expected integer") } fallthrough case 1: depth, err = strconv.Atoi(args[0]) if err != nil { return fmt.Errorf("Wrong argument: expected integer") } default: return fmt.Errorf("Wrong number of arguments to stack") } stack, err := client.Stacktrace(goroutineid, depth) if err != nil { return err } for i := range stack { name := "(nil)" if stack[i].Function != nil { name = stack[i].Function.Name } fmt.Printf("%d. %s\n\t%s:%d (%#v)\n", i, name, stack[i].File, stack[i].Line, stack[i].PC) } return nil }
func funcs(client service.Client, filter string) ([]string, error) { return client.ListFunctions(filter) }