service/rpc1: delete APIv1 (#3881)

We deprecated APIv1 and said we were going to remove it. Here it is.
This commit is contained in:
Alessandro Arzilli
2024-12-16 21:30:47 +01:00
committed by GitHub
parent 84c99e508c
commit 1c434de12e
18 changed files with 20 additions and 1769 deletions

View File

@ -6,8 +6,7 @@ Note that this JSON-RPC interface is served over a streaming socket, *not* over
# API versions
Delve currently supports two versions of its API. By default a headless instance of `dlv` will serve APIv1 for backward compatibility with old clients, however new clients should use APIv2 as new features will only be made available through version 2. To select APIv2 use `--api-version=2` command line argument.
Clients can also select APIv2 by sending a [SetApiVersion](https://pkg.go.dev/github.com/go-delve/delve/service/rpccommon#RPCServer.SetApiVersion) request specifying `APIVersion = 2` after connecting to the headless instance.
Delve currently only supports v2 of its API. Support for v1 was dropped in version v1.24.0 of Delve.
# API version 2 documentation

View File

@ -30,7 +30,7 @@ dlv attach pid [executable] [flags]
```
--accept-multiclient Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
--allow-non-terminal-interactive Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
--api-version int Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
--api-version int Selects JSON-RPC API version when headless. The only valid value is 2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 2)
--backend string Backend selection (see 'dlv help backend'). (default "default")
--check-go-version Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
--headless Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.

View File

@ -30,7 +30,7 @@ Some backends can be configured using environment variables:
```
--accept-multiclient Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
--allow-non-terminal-interactive Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
--api-version int Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
--api-version int Selects JSON-RPC API version when headless. The only valid value is 2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 2)
--backend string Backend selection (see 'dlv help backend'). (default "default")
--build-flags string Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
--check-go-version Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)

View File

@ -27,7 +27,7 @@ dlv core <executable> <core> [flags]
```
--accept-multiclient Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
--allow-non-terminal-interactive Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
--api-version int Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
--api-version int Selects JSON-RPC API version when headless. The only valid value is 2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 2)
--check-go-version Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
--headless Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
--init string Init file, executed by the terminal client.

View File

@ -29,7 +29,7 @@ dlv debug [package] [flags]
```
--accept-multiclient Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
--allow-non-terminal-interactive Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
--api-version int Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
--api-version int Selects JSON-RPC API version when headless. The only valid value is 2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 2)
--backend string Backend selection (see 'dlv help backend'). (default "default")
--build-flags string Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
--check-go-version Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)

View File

@ -29,7 +29,7 @@ dlv exec <path/to/binary> [flags]
```
--accept-multiclient Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
--allow-non-terminal-interactive Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
--api-version int Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
--api-version int Selects JSON-RPC API version when headless. The only valid value is 2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 2)
--backend string Backend selection (see 'dlv help backend'). (default "default")
--check-go-version Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
--disable-aslr Disables address space randomization

View File

@ -41,7 +41,7 @@ and dap modes.
```
--accept-multiclient Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
--allow-non-terminal-interactive Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
--api-version int Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
--api-version int Selects JSON-RPC API version when headless. The only valid value is 2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 2)
--backend string Backend selection (see 'dlv help backend'). (default "default")
--build-flags string Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
--check-go-version Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)

View File

@ -28,7 +28,7 @@ File redirects can also be changed using the 'restart' command.
```
--accept-multiclient Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
--allow-non-terminal-interactive Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
--api-version int Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
--api-version int Selects JSON-RPC API version when headless. The only valid value is 2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 2)
--backend string Backend selection (see 'dlv help backend'). (default "default")
--build-flags string Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
--check-go-version Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)

View File

@ -26,7 +26,7 @@ dlv replay [trace directory] [flags]
```
--accept-multiclient Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
--allow-non-terminal-interactive Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
--api-version int Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
--api-version int Selects JSON-RPC API version when headless. The only valid value is 2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 2)
--check-go-version Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
--headless Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
--init string Init file, executed by the terminal client.

View File

@ -31,7 +31,7 @@ dlv test [package] [flags]
```
--accept-multiclient Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
--allow-non-terminal-interactive Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
--api-version int Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
--api-version int Selects JSON-RPC API version when headless. The only valid value is 2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 2)
--backend string Backend selection (see 'dlv help backend'). (default "default")
--build-flags string Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
--check-go-version Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)

View File

@ -17,7 +17,7 @@ dlv version [flags]
```
--accept-multiclient Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
--allow-non-terminal-interactive Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
--api-version int Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
--api-version int Selects JSON-RPC API version when headless. The only valid value is 2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 2)
--backend string Backend selection (see 'dlv help backend'). (default "default")
--build-flags string Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
--check-go-version Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)

View File

@ -150,7 +150,7 @@ func New(docCall bool) *cobra.Command {
rootCommand.PersistentFlags().BoolVarP(&headless, "headless", "", false, "Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.")
rootCommand.PersistentFlags().BoolVarP(&acceptMulti, "accept-multiclient", "", false, "Allows a headless server to accept multiple client connections via JSON-RPC or DAP.")
rootCommand.PersistentFlags().IntVar(&apiVersion, "api-version", 1, "Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md.")
rootCommand.PersistentFlags().IntVar(&apiVersion, "api-version", 2, "Selects JSON-RPC API version when headless. The only valid value is 2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md.")
must(rootCommand.RegisterFlagCompletionFunc("api-version", cobra.FixedCompletions([]string{"1", "2"}, cobra.ShellCompDirectiveNoFileComp)))
rootCommand.PersistentFlags().StringVar(&initFile, "init", "", "Init file, executed by the terminal client.")
must(rootCommand.MarkPersistentFlagFilename("init"))

View File

@ -1,320 +0,0 @@
package rpc1
import (
"errors"
"fmt"
"log"
"net/rpc"
"net/rpc/jsonrpc"
"sync"
"github.com/go-delve/delve/service/api"
)
// RPCClient is a RPC service.Client.
type RPCClient struct {
addr string
client *rpc.Client
haltMu sync.Mutex
haltReq bool
}
var errAPIUnsupported = errors.New("unsupported")
// NewClient creates a new RPCClient.
func NewClient(addr string) *RPCClient {
client, err := jsonrpc.Dial("tcp", addr)
if err != nil {
log.Fatal("dialing:", err)
}
return &RPCClient{
addr: addr,
client: client,
}
}
func (c *RPCClient) ProcessPid() int {
var pid int
c.call("ProcessPid", nil, &pid)
return pid
}
func (c *RPCClient) Detach(kill bool) error {
return c.call("Detach", kill, nil)
}
func (c *RPCClient) Restart() error {
return c.call("Restart", nil, nil)
}
func (c *RPCClient) GetState() (*api.DebuggerState, error) {
state := new(api.DebuggerState)
err := c.call("State", nil, state)
return state, err
}
func (c *RPCClient) Continue() <-chan *api.DebuggerState {
ch := make(chan *api.DebuggerState)
c.haltMu.Lock()
c.haltReq = false
c.haltMu.Unlock()
go func() {
for {
c.haltMu.Lock()
if c.haltReq {
c.haltMu.Unlock()
close(ch)
return
}
c.haltMu.Unlock()
state := new(api.DebuggerState)
err := c.call("Command", &api.DebuggerCommand{Name: api.Continue}, state)
if err != nil {
state.Err = err
}
if state.Exited {
// Error types apparently cannot be marshalled by Go correctly. Must reset error here.
//lint:ignore ST1005 backwards compatibility
state.Err = fmt.Errorf("Process %d has exited with status %d", c.ProcessPid(), state.ExitStatus)
}
ch <- state
if err != nil || state.Exited {
close(ch)
return
}
isbreakpoint := false
istracepoint := true
for i := range state.Threads {
if state.Threads[i].Breakpoint != nil {
isbreakpoint = true
istracepoint = istracepoint && state.Threads[i].Breakpoint.Tracepoint
}
}
if !isbreakpoint || !istracepoint {
close(ch)
return
}
}
}()
return ch
}
func (c *RPCClient) Next() (*api.DebuggerState, error) {
state := new(api.DebuggerState)
err := c.call("Command", &api.DebuggerCommand{Name: api.Next}, state)
return state, err
}
func (c *RPCClient) Step() (*api.DebuggerState, error) {
state := new(api.DebuggerState)
err := c.call("Command", &api.DebuggerCommand{Name: api.Step}, state)
return state, err
}
func (c *RPCClient) Call(expr string) (*api.DebuggerState, error) {
state := new(api.DebuggerState)
err := c.call("Command", &api.DebuggerCommand{Name: api.Call, Expr: expr}, state)
return state, err
}
func (c *RPCClient) StepInstruction() (*api.DebuggerState, error) {
state := new(api.DebuggerState)
err := c.call("Command", &api.DebuggerCommand{Name: api.StepInstruction}, state)
return state, err
}
func (c *RPCClient) ReverseStepInstruction() (*api.DebuggerState, error) {
state := new(api.DebuggerState)
err := c.call("Command", &api.DebuggerCommand{Name: api.ReverseStepInstruction}, state)
return state, err
}
func (c *RPCClient) SwitchThread(threadID int) (*api.DebuggerState, error) {
state := new(api.DebuggerState)
cmd := &api.DebuggerCommand{
Name: api.SwitchThread,
ThreadID: threadID,
}
err := c.call("Command", cmd, state)
return state, err
}
func (c *RPCClient) SwitchGoroutine(goroutineID int) (*api.DebuggerState, error) {
state := new(api.DebuggerState)
cmd := &api.DebuggerCommand{
Name: api.SwitchGoroutine,
GoroutineID: int64(goroutineID),
}
err := c.call("Command", cmd, state)
return state, err
}
func (c *RPCClient) Halt() (*api.DebuggerState, error) {
state := new(api.DebuggerState)
c.haltMu.Lock()
c.haltReq = true
c.haltMu.Unlock()
err := c.call("Command", &api.DebuggerCommand{Name: api.Halt}, state)
return state, err
}
func (c *RPCClient) GetBreakpoint(id int) (*api.Breakpoint, error) {
breakpoint := new(api.Breakpoint)
err := c.call("GetBreakpoint", id, breakpoint)
return breakpoint, err
}
func (c *RPCClient) GetBreakpointByName(name string) (*api.Breakpoint, error) {
breakpoint := new(api.Breakpoint)
err := c.call("GetBreakpointByName", name, breakpoint)
return breakpoint, err
}
func (c *RPCClient) CreateBreakpoint(breakPoint *api.Breakpoint) (*api.Breakpoint, error) {
newBreakpoint := new(api.Breakpoint)
err := c.call("CreateBreakpoint", breakPoint, &newBreakpoint)
return newBreakpoint, err
}
func (c *RPCClient) ListBreakpoints() ([]*api.Breakpoint, error) {
var breakpoints []*api.Breakpoint
err := c.call("ListBreakpoints", nil, &breakpoints)
return breakpoints, err
}
func (c *RPCClient) ClearBreakpoint(id int) (*api.Breakpoint, error) {
bp := new(api.Breakpoint)
err := c.call("ClearBreakpoint", id, bp)
return bp, err
}
func (c *RPCClient) ClearBreakpointByName(name string) (*api.Breakpoint, error) {
bp := new(api.Breakpoint)
err := c.call("ClearBreakpointByName", name, bp)
return bp, err
}
func (c *RPCClient) AmendBreakpoint(bp *api.Breakpoint) error {
err := c.call("AmendBreakpoint", bp, nil)
return err
}
func (c *RPCClient) CancelNext() error {
return errAPIUnsupported
}
func (c *RPCClient) ListThreads() ([]*api.Thread, error) {
var threads []*api.Thread
err := c.call("ListThreads", nil, &threads)
return threads, err
}
func (c *RPCClient) GetThread(id int) (*api.Thread, error) {
thread := new(api.Thread)
err := c.call("GetThread", id, &thread)
return thread, err
}
func (c *RPCClient) EvalVariable(scope api.EvalScope, symbol string) (*api.Variable, error) {
v := new(api.Variable)
err := c.call("EvalSymbol", EvalSymbolArgs{scope, symbol}, v)
return v, err
}
func (c *RPCClient) SetVariable(scope api.EvalScope, symbol, value string) error {
var unused int
return c.call("SetSymbol", SetSymbolArgs{scope, symbol, value}, &unused)
}
func (c *RPCClient) ListSources(filter string) ([]string, error) {
var sources []string
err := c.call("ListSources", filter, &sources)
return sources, err
}
func (c *RPCClient) ListFunctions(filter string) ([]string, error) {
var funcs []string
err := c.call("ListFunctions", filter, &funcs)
return funcs, err
}
func (c *RPCClient) ListTypes(filter string) ([]string, error) {
var types []string
err := c.call("ListTypes", filter, &types)
return types, err
}
func (c *RPCClient) ListPackageVariables(filter string) ([]api.Variable, error) {
var vars []api.Variable
err := c.call("ListPackageVars", filter, &vars)
return vars, err
}
func (c *RPCClient) ListPackageVariablesFor(threadID int, filter string) ([]api.Variable, error) {
var vars []api.Variable
err := c.call("ListThreadPackageVars", &ThreadListArgs{Id: threadID, Filter: filter}, &vars)
return vars, err
}
func (c *RPCClient) ListLocalVariables(scope api.EvalScope) ([]api.Variable, error) {
var vars []api.Variable
err := c.call("ListLocalVars", scope, &vars)
return vars, err
}
func (c *RPCClient) ListRegisters() (string, error) {
var regs string
err := c.call("ListRegisters", nil, &regs)
return regs, err
}
func (c *RPCClient) ListFunctionArgs(scope api.EvalScope) ([]api.Variable, error) {
var vars []api.Variable
err := c.call("ListFunctionArgs", scope, &vars)
return vars, err
}
func (c *RPCClient) ListGoroutines() ([]*api.Goroutine, error) {
var goroutines []*api.Goroutine
err := c.call("ListGoroutines", nil, &goroutines)
return goroutines, err
}
func (c *RPCClient) Stacktrace(goroutineId, depth int, full bool) ([]api.Stackframe, error) {
var locations []api.Stackframe
err := c.call("StacktraceGoroutine", &StacktraceGoroutineArgs{Id: goroutineId, Depth: depth, Full: full}, &locations)
return locations, err
}
func (c *RPCClient) AttachedToExistingProcess() bool {
var answer bool
c.call("AttachedToExistingProcess", nil, &answer)
return answer
}
func (c *RPCClient) FindLocation(scope api.EvalScope, loc string) ([]api.Location, error) {
var answer []api.Location
err := c.call("FindLocation", FindLocationArgs{scope, loc}, &answer)
return answer, err
}
// DisassembleRange disassembles code between startPC and endPC
func (c *RPCClient) DisassembleRange(scope api.EvalScope, startPC, endPC uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) {
var r api.AsmInstructions
err := c.call("Disassemble", DisassembleRequest{scope, startPC, endPC, flavour}, &r)
return r, err
}
// DisassemblePC disassembles function containing pc
func (c *RPCClient) DisassemblePC(scope api.EvalScope, pc uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) {
var r api.AsmInstructions
err := c.call("Disassemble", DisassembleRequest{scope, pc, 0, flavour}, &r)
return r, err
}
func (c *RPCClient) call(method string, args, reply interface{}) error {
return c.client.Call("RPCServer."+method, args, reply)
}

View File

@ -1,5 +0,0 @@
// Package rpc1 implements version 1 of Delve's API and is only
// kept for backwards compatibility.
// client.go is the old client code used by Delve's frontend (delve/cmd/dlv) and
// is preserved for backwards compatibility with integration tests.
package rpc1

View File

@ -1,329 +0,0 @@
package rpc1
import (
"errors"
"fmt"
"github.com/go-delve/delve/pkg/proc"
"github.com/go-delve/delve/service"
"github.com/go-delve/delve/service/api"
"github.com/go-delve/delve/service/debugger"
)
var defaultLoadConfig = proc.LoadConfig{
FollowPointers: true,
MaxVariableRecurse: 1,
MaxStringLen: 64,
MaxArrayValues: 64,
MaxStructFields: -1,
}
type RPCServer struct {
// config is all the information necessary to start the debugger and server.
config *service.Config
// debugger is a debugger service.
debugger *debugger.Debugger
}
func NewServer(config *service.Config, debugger *debugger.Debugger) *RPCServer {
return &RPCServer{config, debugger}
}
func (s *RPCServer) ProcessPid(arg1 interface{}, pid *int) error {
*pid = s.debugger.ProcessPid()
return nil
}
func (s *RPCServer) Detach(kill bool, ret *int) error {
return s.debugger.Detach(kill)
}
func (s *RPCServer) Restart(arg1 interface{}, arg2 *int) error {
if s.config.Debugger.AttachPid != 0 {
return errors.New("cannot restart process Delve did not create")
}
_, err := s.debugger.Restart(false, "", false, nil, [3]string{}, false)
return err
}
func (s *RPCServer) State(arg interface{}, state *api.DebuggerState) error {
st, err := s.debugger.State(false)
if err != nil {
return err
}
*state = *st
return nil
}
func (s *RPCServer) Command(command *api.DebuggerCommand, cb service.RPCCallback) {
st, err := s.debugger.Command(command, cb.SetupDoneChan(), cb.DisconnectChan())
cb.Return(st, err)
}
func (s *RPCServer) GetBreakpoint(id int, breakpoint *api.Breakpoint) error {
bp := s.debugger.FindBreakpoint(id)
if bp == nil {
return fmt.Errorf("no breakpoint with id %d", id)
}
*breakpoint = *bp
return nil
}
func (s *RPCServer) GetBreakpointByName(name string, breakpoint *api.Breakpoint) error {
bp := s.debugger.FindBreakpointByName(name)
if bp == nil {
return fmt.Errorf("no breakpoint with name %s", name)
}
*breakpoint = *bp
return nil
}
type StacktraceGoroutineArgs struct {
Id int
Depth int
Full bool
}
func (s *RPCServer) StacktraceGoroutine(args *StacktraceGoroutineArgs, locations *[]api.Stackframe) error {
var loadcfg *proc.LoadConfig = nil
if args.Full {
loadcfg = &defaultLoadConfig
}
locs, err := s.debugger.Stacktrace(int64(args.Id), args.Depth, 0)
if err != nil {
return err
}
*locations, err = s.debugger.ConvertStacktrace(locs, loadcfg)
return err
}
func (s *RPCServer) ListBreakpoints(arg interface{}, breakpoints *[]*api.Breakpoint) error {
*breakpoints = s.debugger.Breakpoints(false)
return nil
}
func (s *RPCServer) CreateBreakpoint(bp, newBreakpoint *api.Breakpoint) error {
if err := api.ValidBreakpointName(bp.Name); err != nil {
return err
}
createdbp, err := s.debugger.CreateBreakpoint(bp, "", nil, false)
if err != nil {
return err
}
*newBreakpoint = *createdbp
return nil
}
func (s *RPCServer) ClearBreakpoint(id int, breakpoint *api.Breakpoint) error {
bp := s.debugger.FindBreakpoint(id)
if bp == nil {
return fmt.Errorf("no breakpoint with id %d", id)
}
deleted, err := s.debugger.ClearBreakpoint(bp)
if err != nil {
return err
}
*breakpoint = *deleted
return nil
}
func (s *RPCServer) ClearBreakpointByName(name string, breakpoint *api.Breakpoint) error {
bp := s.debugger.FindBreakpointByName(name)
if bp == nil {
return fmt.Errorf("no breakpoint with name %s", name)
}
deleted, err := s.debugger.ClearBreakpoint(bp)
if err != nil {
return err
}
*breakpoint = *deleted
return nil
}
func (s *RPCServer) AmendBreakpoint(amend *api.Breakpoint, unused *int) error {
*unused = 0
if err := api.ValidBreakpointName(amend.Name); err != nil {
return err
}
return s.debugger.AmendBreakpoint(amend)
}
func (s *RPCServer) ListThreads(arg interface{}, threads *[]*api.Thread) (err error) {
pthreads, err := s.debugger.Threads()
if err != nil {
return err
}
s.debugger.LockTarget()
defer s.debugger.UnlockTarget()
*threads = api.ConvertThreads(pthreads, s.debugger.ConvertThreadBreakpoint)
return nil
}
func (s *RPCServer) GetThread(id int, thread *api.Thread) error {
t, err := s.debugger.FindThread(id)
if err != nil {
return err
}
if t == nil {
return fmt.Errorf("no thread with id %d", id)
}
s.debugger.LockTarget()
defer s.debugger.UnlockTarget()
*thread = *api.ConvertThread(t, s.debugger.ConvertThreadBreakpoint(t))
return nil
}
func (s *RPCServer) ListPackageVars(filter string, variables *[]api.Variable) error {
vars, err := s.debugger.PackageVariables(filter, defaultLoadConfig)
if err != nil {
return err
}
*variables = api.ConvertVars(vars)
return nil
}
type ThreadListArgs struct {
Id int
Filter string
}
func (s *RPCServer) ListThreadPackageVars(args *ThreadListArgs, variables *[]api.Variable) error {
vars, err := s.debugger.PackageVariables(args.Filter, defaultLoadConfig)
if err != nil {
return err
}
*variables = api.ConvertVars(vars)
return nil
}
func (s *RPCServer) ListRegisters(arg interface{}, registers *string) error {
state, err := s.debugger.State(false)
if err != nil {
return err
}
dregs, err := s.debugger.ThreadRegisters(state.CurrentThread.ID)
if err != nil {
return err
}
regs := api.Registers(api.ConvertRegisters(dregs, s.debugger.DwarfRegisterToString, false))
*registers = regs.String()
return nil
}
func (s *RPCServer) ListLocalVars(scope api.EvalScope, variables *[]api.Variable) error {
vars, err := s.debugger.LocalVariables(scope.GoroutineID, scope.Frame, scope.DeferredCall, defaultLoadConfig)
if err != nil {
return err
}
*variables = api.ConvertVars(vars)
return nil
}
func (s *RPCServer) ListFunctionArgs(scope api.EvalScope, variables *[]api.Variable) error {
vars, err := s.debugger.FunctionArguments(scope.GoroutineID, scope.Frame, scope.DeferredCall, defaultLoadConfig)
if err != nil {
return err
}
*variables = api.ConvertVars(vars)
return nil
}
type EvalSymbolArgs struct {
Scope api.EvalScope
Symbol string
}
func (s *RPCServer) EvalSymbol(args EvalSymbolArgs, variable *api.Variable) error {
v, err := s.debugger.EvalVariableInScope(args.Scope.GoroutineID, args.Scope.Frame, args.Scope.DeferredCall, args.Symbol, defaultLoadConfig)
if err != nil {
return err
}
*variable = *api.ConvertVar(v)
return nil
}
type SetSymbolArgs struct {
Scope api.EvalScope
Symbol string
Value string
}
func (s *RPCServer) SetSymbol(args SetSymbolArgs, unused *int) error {
*unused = 0
return s.debugger.SetVariableInScope(args.Scope.GoroutineID, args.Scope.Frame, args.Scope.DeferredCall, args.Symbol, args.Value)
}
func (s *RPCServer) ListSources(filter string, sources *[]string) error {
ss, err := s.debugger.Sources(filter)
if err != nil {
return err
}
*sources = ss
return nil
}
func (s *RPCServer) ListFunctions(filter string, followCalls int, funcs *[]string) error {
fns, err := s.debugger.Functions(filter, followCalls)
if err != nil {
return err
}
*funcs = fns
return nil
}
func (s *RPCServer) ListTypes(filter string, types *[]string) error {
tps, err := s.debugger.Types(filter)
if err != nil {
return err
}
*types = tps
return nil
}
func (s *RPCServer) ListGoroutines(arg interface{}, goroutines *[]*api.Goroutine) error {
gs, _, err := s.debugger.Goroutines(0, 0)
if err != nil {
return err
}
s.debugger.LockTarget()
s.debugger.UnlockTarget()
*goroutines = api.ConvertGoroutines(s.debugger.Target(), gs)
return nil
}
func (s *RPCServer) AttachedToExistingProcess(arg interface{}, answer *bool) error {
if s.config.Debugger.AttachPid != 0 {
*answer = true
}
return nil
}
type FindLocationArgs struct {
Scope api.EvalScope
Loc string
}
func (s *RPCServer) FindLocation(args FindLocationArgs, answer *[]api.Location) error {
var err error
*answer, _, err = s.debugger.FindLocation(args.Scope.GoroutineID, args.Scope.Frame, args.Scope.DeferredCall, args.Loc, false, nil)
return err
}
type DisassembleRequest struct {
Scope api.EvalScope
StartPC, EndPC uint64
Flavour api.AssemblyFlavour
}
func (s *RPCServer) Disassemble(args DisassembleRequest, answer *api.AsmInstructions) error {
insts, err := s.debugger.Disassemble(args.Scope.GoroutineID, args.StartPC, args.EndPC)
if err != nil {
return err
}
*answer = make(api.AsmInstructions, len(insts))
for i := range insts {
(*answer)[i] = api.ConvertAsmInstruction(insts[i], s.debugger.AsmInstructionText(&insts[i], proc.AssemblyFlavour(args.Flavour)))
}
return nil
}

View File

@ -24,7 +24,6 @@ import (
"github.com/go-delve/delve/service/dap"
"github.com/go-delve/delve/service/debugger"
"github.com/go-delve/delve/service/internal/sameuser"
"github.com/go-delve/delve/service/rpc1"
"github.com/go-delve/delve/service/rpc2"
)
@ -39,8 +38,6 @@ type ServerImpl struct {
stopChan chan struct{}
// debugger is the debugger service.
debugger *debugger.Debugger
// s1 is APIv1 server.
s1 *rpc1.RPCServer
// s2 is APIv2 server.
s2 *rpc2.RPCServer
// maps of served methods, one for each supported API.
@ -110,10 +107,11 @@ func (s *ServerImpl) Stop() error {
func (s *ServerImpl) Run() error {
var err error
if s.config.APIVersion < 2 {
s.config.APIVersion = 1
if s.config.APIVersion == 0 {
s.config.APIVersion = 2
}
if s.config.APIVersion > 2 {
if s.config.APIVersion != 2 {
return errors.New("unknown API version")
}
@ -123,17 +121,13 @@ func (s *ServerImpl) Run() error {
return err
}
s.s1 = rpc1.NewServer(s.config, s.debugger)
s.s2 = rpc2.NewServer(s.config, s.debugger)
rpcServer := &RPCServer{s}
s.methodMaps = make([]map[string]*methodType, 2)
s.methodMaps[0] = map[string]*methodType{}
s.methodMaps[1] = map[string]*methodType{}
suitableMethods(s.s1, s.methodMaps[0], s.log)
suitableMethods(rpcServer, s.methodMaps[0], s.log)
suitableMethods(s.s2, s.methodMaps[1], s.log)
suitableMethods(rpcServer, s.methodMaps[1], s.log)
@ -452,10 +446,7 @@ func (s *RPCServer) GetVersion(args api.GetVersionIn, out *api.GetVersionOut) er
// SetApiVersion changes version of the API being served.
func (s *RPCServer) SetApiVersion(args api.SetAPIVersionIn, out *api.SetAPIVersionOut) error {
if args.APIVersion < 2 {
args.APIVersion = 1
}
if args.APIVersion > 2 {
if args.APIVersion != 2 {
return errors.New("unknown API version")
}
s.s.config.APIVersion = args.APIVersion

View File

@ -8,9 +8,8 @@ import (
"strings"
"testing"
"github.com/go-delve/delve/service"
"github.com/go-delve/delve/service/api"
"github.com/go-delve/delve/service/rpc1"
"github.com/go-delve/delve/service/rpc2"
)
func assertNoError(err error, t *testing.T, s string) {
@ -65,15 +64,8 @@ type BreakpointLister interface {
ListBreakpoints() ([]*api.Breakpoint, error)
}
func countBreakpoints(t *testing.T, c interface{}) int {
var bps []*api.Breakpoint
var err error
switch c := c.(type) {
case *rpc2.RPCClient:
bps, err = c.ListBreakpoints(false)
case *rpc1.RPCClient:
bps, err = c.ListBreakpoints()
}
func countBreakpoints(t *testing.T, c service.Client) int {
bps, err := c.ListBreakpoints(false)
assertNoError(err, t, "ListBreakpoints()")
bpcount := 0
for _, bp := range bps {

File diff suppressed because it is too large Load Diff