github.com/cnboonhan/delve@v0.0.0-20230908061759-363f2388c2fb/service/rpc2/client.go (about)

     1  package rpc2
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"net"
     7  	"net/rpc"
     8  	"net/rpc/jsonrpc"
     9  	"time"
    10  
    11  	"github.com/go-delve/delve/service"
    12  	"github.com/go-delve/delve/service/api"
    13  )
    14  
    15  // RPCClient is a RPC service.Client.
    16  type RPCClient struct {
    17  	client *rpc.Client
    18  
    19  	retValLoadCfg *api.LoadConfig
    20  }
    21  
    22  // Ensure the implementation satisfies the interface.
    23  var _ service.Client = &RPCClient{}
    24  
    25  // NewClient creates a new RPCClient.
    26  func NewClient(addr string) *RPCClient {
    27  	client, err := jsonrpc.Dial("tcp", addr)
    28  	if err != nil {
    29  		log.Fatal("dialing:", err)
    30  	}
    31  	return newFromRPCClient(client)
    32  }
    33  
    34  func newFromRPCClient(client *rpc.Client) *RPCClient {
    35  	c := &RPCClient{client: client}
    36  	c.call("SetApiVersion", api.SetAPIVersionIn{APIVersion: 2}, &api.SetAPIVersionOut{})
    37  	return c
    38  }
    39  
    40  // NewClientFromConn creates a new RPCClient from the given connection.
    41  func NewClientFromConn(conn net.Conn) *RPCClient {
    42  	return newFromRPCClient(jsonrpc.NewClient(conn))
    43  }
    44  
    45  func (c *RPCClient) ProcessPid() int {
    46  	out := new(ProcessPidOut)
    47  	c.call("ProcessPid", ProcessPidIn{}, out)
    48  	return out.Pid
    49  }
    50  
    51  func (c *RPCClient) BuildID() string {
    52  	out := new(BuildIDOut)
    53  	c.call("BuildID", BuildIDIn{}, out)
    54  	return out.BuildID
    55  }
    56  
    57  func (c *RPCClient) LastModified() time.Time {
    58  	out := new(LastModifiedOut)
    59  	c.call("LastModified", LastModifiedIn{}, out)
    60  	return out.Time
    61  }
    62  
    63  func (c *RPCClient) Detach(kill bool) error {
    64  	defer c.client.Close()
    65  	out := new(DetachOut)
    66  	return c.call("Detach", DetachIn{kill}, out)
    67  }
    68  
    69  func (c *RPCClient) Restart(rebuild bool) ([]api.DiscardedBreakpoint, error) {
    70  	out := new(RestartOut)
    71  	err := c.call("Restart", RestartIn{"", false, nil, false, rebuild, [3]string{}}, out)
    72  	return out.DiscardedBreakpoints, err
    73  }
    74  
    75  func (c *RPCClient) RestartFrom(rerecord bool, pos string, resetArgs bool, newArgs []string, newRedirects [3]string, rebuild bool) ([]api.DiscardedBreakpoint, error) {
    76  	out := new(RestartOut)
    77  	err := c.call("Restart", RestartIn{pos, resetArgs, newArgs, rerecord, rebuild, newRedirects}, out)
    78  	return out.DiscardedBreakpoints, err
    79  }
    80  
    81  func (c *RPCClient) GetState() (*api.DebuggerState, error) {
    82  	var out StateOut
    83  	err := c.call("State", StateIn{NonBlocking: false}, &out)
    84  	return out.State, err
    85  }
    86  
    87  func (c *RPCClient) GetStateNonBlocking() (*api.DebuggerState, error) {
    88  	var out StateOut
    89  	err := c.call("State", StateIn{NonBlocking: true}, &out)
    90  	return out.State, err
    91  }
    92  
    93  func (c *RPCClient) Continue() <-chan *api.DebuggerState {
    94  	return c.continueDir(api.Continue)
    95  }
    96  
    97  func (c *RPCClient) Rewind() <-chan *api.DebuggerState {
    98  	return c.continueDir(api.Rewind)
    99  }
   100  
   101  func (c *RPCClient) DirectionCongruentContinue() <-chan *api.DebuggerState {
   102  	return c.continueDir(api.DirectionCongruentContinue)
   103  }
   104  
   105  func (c *RPCClient) continueDir(cmd string) <-chan *api.DebuggerState {
   106  	ch := make(chan *api.DebuggerState)
   107  	go func() {
   108  		for {
   109  			out := new(CommandOut)
   110  			err := c.call("Command", &api.DebuggerCommand{Name: cmd, ReturnInfoLoadConfig: c.retValLoadCfg}, &out)
   111  			state := out.State
   112  			if err != nil {
   113  				state.Err = err
   114  			}
   115  			if state.Exited {
   116  				// Error types apparently cannot be marshalled by Go correctly. Must reset error here.
   117  				//lint:ignore ST1005 backwards compatibility
   118  				state.Err = fmt.Errorf("Process %d has exited with status %d", c.ProcessPid(), state.ExitStatus)
   119  			}
   120  			ch <- &state
   121  			if err != nil || state.Exited {
   122  				close(ch)
   123  				return
   124  			}
   125  
   126  			isbreakpoint := false
   127  			istracepoint := true
   128  			for i := range state.Threads {
   129  				if state.Threads[i].Breakpoint != nil {
   130  					isbreakpoint = true
   131  					istracepoint = istracepoint && (state.Threads[i].Breakpoint.Tracepoint || state.Threads[i].Breakpoint.TraceReturn)
   132  				}
   133  			}
   134  
   135  			if !isbreakpoint || !istracepoint {
   136  				close(ch)
   137  				return
   138  			}
   139  		}
   140  	}()
   141  	return ch
   142  }
   143  
   144  func (c *RPCClient) Next() (*api.DebuggerState, error) {
   145  	var out CommandOut
   146  	err := c.call("Command", api.DebuggerCommand{Name: api.Next, ReturnInfoLoadConfig: c.retValLoadCfg}, &out)
   147  	return &out.State, err
   148  }
   149  
   150  func (c *RPCClient) ReverseNext() (*api.DebuggerState, error) {
   151  	var out CommandOut
   152  	err := c.call("Command", api.DebuggerCommand{Name: api.ReverseNext, ReturnInfoLoadConfig: c.retValLoadCfg}, &out)
   153  	return &out.State, err
   154  }
   155  
   156  func (c *RPCClient) Step() (*api.DebuggerState, error) {
   157  	var out CommandOut
   158  	err := c.call("Command", api.DebuggerCommand{Name: api.Step, ReturnInfoLoadConfig: c.retValLoadCfg}, &out)
   159  	return &out.State, err
   160  }
   161  
   162  func (c *RPCClient) ReverseStep() (*api.DebuggerState, error) {
   163  	var out CommandOut
   164  	err := c.call("Command", api.DebuggerCommand{Name: api.ReverseStep, ReturnInfoLoadConfig: c.retValLoadCfg}, &out)
   165  	return &out.State, err
   166  }
   167  
   168  func (c *RPCClient) StepOut() (*api.DebuggerState, error) {
   169  	var out CommandOut
   170  	err := c.call("Command", api.DebuggerCommand{Name: api.StepOut, ReturnInfoLoadConfig: c.retValLoadCfg}, &out)
   171  	return &out.State, err
   172  }
   173  
   174  func (c *RPCClient) ReverseStepOut() (*api.DebuggerState, error) {
   175  	var out CommandOut
   176  	err := c.call("Command", api.DebuggerCommand{Name: api.ReverseStepOut, ReturnInfoLoadConfig: c.retValLoadCfg}, &out)
   177  	return &out.State, err
   178  }
   179  
   180  func (c *RPCClient) Call(goroutineID int64, expr string, unsafe bool) (*api.DebuggerState, error) {
   181  	var out CommandOut
   182  	err := c.call("Command", api.DebuggerCommand{Name: api.Call, ReturnInfoLoadConfig: c.retValLoadCfg, Expr: expr, UnsafeCall: unsafe, GoroutineID: goroutineID}, &out)
   183  	return &out.State, err
   184  }
   185  
   186  func (c *RPCClient) StepInstruction() (*api.DebuggerState, error) {
   187  	var out CommandOut
   188  	err := c.call("Command", api.DebuggerCommand{Name: api.StepInstruction}, &out)
   189  	return &out.State, err
   190  }
   191  
   192  func (c *RPCClient) ReverseStepInstruction() (*api.DebuggerState, error) {
   193  	var out CommandOut
   194  	err := c.call("Command", api.DebuggerCommand{Name: api.ReverseStepInstruction}, &out)
   195  	return &out.State, err
   196  }
   197  
   198  func (c *RPCClient) SwitchThread(threadID int) (*api.DebuggerState, error) {
   199  	var out CommandOut
   200  	cmd := api.DebuggerCommand{
   201  		Name:     api.SwitchThread,
   202  		ThreadID: threadID,
   203  	}
   204  	err := c.call("Command", cmd, &out)
   205  	return &out.State, err
   206  }
   207  
   208  func (c *RPCClient) SwitchGoroutine(goroutineID int64) (*api.DebuggerState, error) {
   209  	var out CommandOut
   210  	cmd := api.DebuggerCommand{
   211  		Name:        api.SwitchGoroutine,
   212  		GoroutineID: goroutineID,
   213  	}
   214  	err := c.call("Command", cmd, &out)
   215  	return &out.State, err
   216  }
   217  
   218  func (c *RPCClient) Halt() (*api.DebuggerState, error) {
   219  	var out CommandOut
   220  	err := c.call("Command", api.DebuggerCommand{Name: api.Halt}, &out)
   221  	return &out.State, err
   222  }
   223  
   224  func (c *RPCClient) GetBufferedTracepoints() ([]api.TracepointResult, error) {
   225  	var out GetBufferedTracepointsOut
   226  	err := c.call("GetBufferedTracepoints", GetBufferedTracepointsIn{}, &out)
   227  	return out.TracepointResults, err
   228  }
   229  
   230  func (c *RPCClient) GetBreakpoint(id int) (*api.Breakpoint, error) {
   231  	var out GetBreakpointOut
   232  	err := c.call("GetBreakpoint", GetBreakpointIn{id, ""}, &out)
   233  	return &out.Breakpoint, err
   234  }
   235  
   236  func (c *RPCClient) GetBreakpointByName(name string) (*api.Breakpoint, error) {
   237  	var out GetBreakpointOut
   238  	err := c.call("GetBreakpoint", GetBreakpointIn{0, name}, &out)
   239  	return &out.Breakpoint, err
   240  }
   241  
   242  // CreateBreakpoint will send a request to the RPC server to create a breakpoint.
   243  // Please refer to the documentation for `Debugger.CreateBreakpoint` for a description of how
   244  // the requested breakpoint parameters are interpreted and used:
   245  // https://pkg.go.dev/github.com/go-delve/delve/service/debugger#Debugger.CreateBreakpoint
   246  func (c *RPCClient) CreateBreakpoint(breakPoint *api.Breakpoint) (*api.Breakpoint, error) {
   247  	var out CreateBreakpointOut
   248  	err := c.call("CreateBreakpoint", CreateBreakpointIn{*breakPoint, "", nil, false}, &out)
   249  	return &out.Breakpoint, err
   250  }
   251  
   252  // CreateBreakpointWithExpr is like CreateBreakpoint but will also set a
   253  // location expression to be used to restore the breakpoint after it is
   254  // disabled.
   255  func (c *RPCClient) CreateBreakpointWithExpr(breakPoint *api.Breakpoint, locExpr string, substitutePathRules [][2]string, suspended bool) (*api.Breakpoint, error) {
   256  	var out CreateBreakpointOut
   257  	err := c.call("CreateBreakpoint", CreateBreakpointIn{*breakPoint, locExpr, substitutePathRules, suspended}, &out)
   258  	return &out.Breakpoint, err
   259  }
   260  
   261  func (c *RPCClient) CreateEBPFTracepoint(fnName string) error {
   262  	var out CreateEBPFTracepointOut
   263  	return c.call("CreateEBPFTracepoint", CreateEBPFTracepointIn{FunctionName: fnName}, &out)
   264  }
   265  
   266  func (c *RPCClient) CreateWatchpoint(scope api.EvalScope, expr string, wtype api.WatchType) (*api.Breakpoint, error) {
   267  	var out CreateWatchpointOut
   268  	err := c.call("CreateWatchpoint", CreateWatchpointIn{scope, expr, wtype}, &out)
   269  	return out.Breakpoint, err
   270  }
   271  
   272  func (c *RPCClient) ListBreakpoints(all bool) ([]*api.Breakpoint, error) {
   273  	var out ListBreakpointsOut
   274  	err := c.call("ListBreakpoints", ListBreakpointsIn{all}, &out)
   275  	return out.Breakpoints, err
   276  }
   277  
   278  func (c *RPCClient) ClearBreakpoint(id int) (*api.Breakpoint, error) {
   279  	var out ClearBreakpointOut
   280  	err := c.call("ClearBreakpoint", ClearBreakpointIn{id, ""}, &out)
   281  	return out.Breakpoint, err
   282  }
   283  
   284  func (c *RPCClient) ClearBreakpointByName(name string) (*api.Breakpoint, error) {
   285  	var out ClearBreakpointOut
   286  	err := c.call("ClearBreakpoint", ClearBreakpointIn{0, name}, &out)
   287  	return out.Breakpoint, err
   288  }
   289  
   290  func (c *RPCClient) ToggleBreakpoint(id int) (*api.Breakpoint, error) {
   291  	var out ToggleBreakpointOut
   292  	err := c.call("ToggleBreakpoint", ToggleBreakpointIn{id, ""}, &out)
   293  	return out.Breakpoint, err
   294  }
   295  
   296  func (c *RPCClient) ToggleBreakpointByName(name string) (*api.Breakpoint, error) {
   297  	var out ToggleBreakpointOut
   298  	err := c.call("ToggleBreakpoint", ToggleBreakpointIn{0, name}, &out)
   299  	return out.Breakpoint, err
   300  }
   301  
   302  func (c *RPCClient) AmendBreakpoint(bp *api.Breakpoint) error {
   303  	out := new(AmendBreakpointOut)
   304  	err := c.call("AmendBreakpoint", AmendBreakpointIn{*bp}, out)
   305  	return err
   306  }
   307  
   308  func (c *RPCClient) CancelNext() error {
   309  	var out CancelNextOut
   310  	return c.call("CancelNext", CancelNextIn{}, &out)
   311  }
   312  
   313  func (c *RPCClient) ListThreads() ([]*api.Thread, error) {
   314  	var out ListThreadsOut
   315  	err := c.call("ListThreads", ListThreadsIn{}, &out)
   316  	return out.Threads, err
   317  }
   318  
   319  func (c *RPCClient) GetThread(id int) (*api.Thread, error) {
   320  	var out GetThreadOut
   321  	err := c.call("GetThread", GetThreadIn{id}, &out)
   322  	return out.Thread, err
   323  }
   324  
   325  func (c *RPCClient) EvalVariable(scope api.EvalScope, expr string, cfg api.LoadConfig) (*api.Variable, error) {
   326  	var out EvalOut
   327  	err := c.call("Eval", EvalIn{scope, expr, &cfg}, &out)
   328  	return out.Variable, err
   329  }
   330  
   331  func (c *RPCClient) SetVariable(scope api.EvalScope, symbol, value string) error {
   332  	out := new(SetOut)
   333  	return c.call("Set", SetIn{scope, symbol, value}, out)
   334  }
   335  
   336  func (c *RPCClient) ListSources(filter string) ([]string, error) {
   337  	sources := new(ListSourcesOut)
   338  	err := c.call("ListSources", ListSourcesIn{filter}, sources)
   339  	return sources.Sources, err
   340  }
   341  
   342  func (c *RPCClient) ListFunctions(filter string) ([]string, error) {
   343  	funcs := new(ListFunctionsOut)
   344  	err := c.call("ListFunctions", ListFunctionsIn{filter}, funcs)
   345  	return funcs.Funcs, err
   346  }
   347  
   348  func (c *RPCClient) ListTypes(filter string) ([]string, error) {
   349  	types := new(ListTypesOut)
   350  	err := c.call("ListTypes", ListTypesIn{filter}, types)
   351  	return types.Types, err
   352  }
   353  
   354  func (c *RPCClient) ListPackageVariables(filter string, cfg api.LoadConfig) ([]api.Variable, error) {
   355  	var out ListPackageVarsOut
   356  	err := c.call("ListPackageVars", ListPackageVarsIn{filter, cfg}, &out)
   357  	return out.Variables, err
   358  }
   359  
   360  func (c *RPCClient) ListLocalVariables(scope api.EvalScope, cfg api.LoadConfig) ([]api.Variable, error) {
   361  	var out ListLocalVarsOut
   362  	err := c.call("ListLocalVars", ListLocalVarsIn{scope, cfg}, &out)
   363  	return out.Variables, err
   364  }
   365  
   366  func (c *RPCClient) ListThreadRegisters(threadID int, includeFp bool) (api.Registers, error) {
   367  	out := new(ListRegistersOut)
   368  	err := c.call("ListRegisters", ListRegistersIn{ThreadID: threadID, IncludeFp: includeFp, Scope: nil}, out)
   369  	return out.Regs, err
   370  }
   371  
   372  func (c *RPCClient) ListScopeRegisters(scope api.EvalScope, includeFp bool) (api.Registers, error) {
   373  	out := new(ListRegistersOut)
   374  	err := c.call("ListRegisters", ListRegistersIn{ThreadID: 0, IncludeFp: includeFp, Scope: &scope}, out)
   375  	return out.Regs, err
   376  }
   377  
   378  func (c *RPCClient) ListFunctionArgs(scope api.EvalScope, cfg api.LoadConfig) ([]api.Variable, error) {
   379  	var out ListFunctionArgsOut
   380  	err := c.call("ListFunctionArgs", ListFunctionArgsIn{scope, cfg}, &out)
   381  	return out.Args, err
   382  }
   383  
   384  func (c *RPCClient) ListGoroutines(start, count int) ([]*api.Goroutine, int, error) {
   385  	var out ListGoroutinesOut
   386  	err := c.call("ListGoroutines", ListGoroutinesIn{start, count, nil, api.GoroutineGroupingOptions{}, nil}, &out)
   387  	return out.Goroutines, out.Nextg, err
   388  }
   389  
   390  func (c *RPCClient) ListGoroutinesWithFilter(start, count int, filters []api.ListGoroutinesFilter, group *api.GoroutineGroupingOptions, scope *api.EvalScope) ([]*api.Goroutine, []api.GoroutineGroup, int, bool, error) {
   391  	if group == nil {
   392  		group = &api.GoroutineGroupingOptions{}
   393  	}
   394  	var out ListGoroutinesOut
   395  	err := c.call("ListGoroutines", ListGoroutinesIn{start, count, filters, *group, scope}, &out)
   396  	return out.Goroutines, out.Groups, out.Nextg, out.TooManyGroups, err
   397  }
   398  
   399  func (c *RPCClient) Stacktrace(goroutineId int64, depth int, opts api.StacktraceOptions, cfg *api.LoadConfig) ([]api.Stackframe, error) {
   400  	var out StacktraceOut
   401  	err := c.call("Stacktrace", StacktraceIn{goroutineId, depth, false, false, opts, cfg}, &out)
   402  	return out.Locations, err
   403  }
   404  
   405  func (c *RPCClient) Ancestors(goroutineID int64, numAncestors int, depth int) ([]api.Ancestor, error) {
   406  	var out AncestorsOut
   407  	err := c.call("Ancestors", AncestorsIn{goroutineID, numAncestors, depth}, &out)
   408  	return out.Ancestors, err
   409  }
   410  
   411  func (c *RPCClient) AttachedToExistingProcess() bool {
   412  	out := new(AttachedToExistingProcessOut)
   413  	c.call("AttachedToExistingProcess", AttachedToExistingProcessIn{}, out)
   414  	return out.Answer
   415  }
   416  
   417  func (c *RPCClient) FindLocation(scope api.EvalScope, loc string, findInstructions bool, substitutePathRules [][2]string) ([]api.Location, string, error) {
   418  	var out FindLocationOut
   419  	err := c.call("FindLocation", FindLocationIn{scope, loc, !findInstructions, substitutePathRules}, &out)
   420  	return out.Locations, out.SubstituteLocExpr, err
   421  }
   422  
   423  // DisassembleRange disassembles code between startPC and endPC
   424  func (c *RPCClient) DisassembleRange(scope api.EvalScope, startPC, endPC uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) {
   425  	var out DisassembleOut
   426  	err := c.call("Disassemble", DisassembleIn{scope, startPC, endPC, flavour}, &out)
   427  	return out.Disassemble, err
   428  }
   429  
   430  // DisassemblePC disassembles function containing pc
   431  func (c *RPCClient) DisassemblePC(scope api.EvalScope, pc uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) {
   432  	var out DisassembleOut
   433  	err := c.call("Disassemble", DisassembleIn{scope, pc, 0, flavour}, &out)
   434  	return out.Disassemble, err
   435  }
   436  
   437  // Recorded returns true if the debugger target is a recording.
   438  func (c *RPCClient) Recorded() bool {
   439  	out := new(RecordedOut)
   440  	c.call("Recorded", RecordedIn{}, out)
   441  	return out.Recorded
   442  }
   443  
   444  // TraceDirectory returns the path to the trace directory for a recording.
   445  func (c *RPCClient) TraceDirectory() (string, error) {
   446  	var out RecordedOut
   447  	err := c.call("Recorded", RecordedIn{}, &out)
   448  	return out.TraceDirectory, err
   449  }
   450  
   451  // Checkpoint sets a checkpoint at the current position.
   452  func (c *RPCClient) Checkpoint(where string) (checkpointID int, err error) {
   453  	var out CheckpointOut
   454  	err = c.call("Checkpoint", CheckpointIn{where}, &out)
   455  	return out.ID, err
   456  }
   457  
   458  // ListCheckpoints gets all checkpoints.
   459  func (c *RPCClient) ListCheckpoints() ([]api.Checkpoint, error) {
   460  	var out ListCheckpointsOut
   461  	err := c.call("ListCheckpoints", ListCheckpointsIn{}, &out)
   462  	return out.Checkpoints, err
   463  }
   464  
   465  // ClearCheckpoint removes a checkpoint
   466  func (c *RPCClient) ClearCheckpoint(id int) error {
   467  	var out ClearCheckpointOut
   468  	err := c.call("ClearCheckpoint", ClearCheckpointIn{id}, &out)
   469  	return err
   470  }
   471  
   472  func (c *RPCClient) SetReturnValuesLoadConfig(cfg *api.LoadConfig) {
   473  	c.retValLoadCfg = cfg
   474  }
   475  
   476  func (c *RPCClient) FunctionReturnLocations(fnName string) ([]uint64, error) {
   477  	var out FunctionReturnLocationsOut
   478  	err := c.call("FunctionReturnLocations", FunctionReturnLocationsIn{fnName}, &out)
   479  	return out.Addrs, err
   480  }
   481  
   482  func (c *RPCClient) IsMulticlient() bool {
   483  	var out IsMulticlientOut
   484  	c.call("IsMulticlient", IsMulticlientIn{}, &out)
   485  	return out.IsMulticlient
   486  }
   487  
   488  func (c *RPCClient) Disconnect(cont bool) error {
   489  	if cont {
   490  		out := new(CommandOut)
   491  		c.client.Go("RPCServer.Command", &api.DebuggerCommand{Name: api.Continue, ReturnInfoLoadConfig: c.retValLoadCfg}, &out, nil)
   492  	}
   493  	return c.client.Close()
   494  }
   495  
   496  func (c *RPCClient) ListDynamicLibraries() ([]api.Image, error) {
   497  	var out ListDynamicLibrariesOut
   498  	c.call("ListDynamicLibraries", ListDynamicLibrariesIn{}, &out)
   499  	return out.List, nil
   500  }
   501  
   502  func (c *RPCClient) ExamineMemory(address uint64, count int) ([]byte, bool, error) {
   503  	out := &ExaminedMemoryOut{}
   504  
   505  	err := c.call("ExamineMemory", ExamineMemoryIn{Length: count, Address: address}, out)
   506  	if err != nil {
   507  		return nil, false, err
   508  	}
   509  	return out.Mem, out.IsLittleEndian, nil
   510  }
   511  
   512  func (c *RPCClient) StopRecording() error {
   513  	return c.call("StopRecording", StopRecordingIn{}, &StopRecordingOut{})
   514  }
   515  
   516  func (c *RPCClient) CoreDumpStart(dest string) (api.DumpState, error) {
   517  	out := &DumpStartOut{}
   518  	err := c.call("DumpStart", DumpStartIn{Destination: dest}, out)
   519  	return out.State, err
   520  }
   521  
   522  func (c *RPCClient) CoreDumpWait(msec int) api.DumpState {
   523  	out := &DumpWaitOut{}
   524  	_ = c.call("DumpWait", DumpWaitIn{Wait: msec}, out)
   525  	return out.State
   526  }
   527  
   528  func (c *RPCClient) CoreDumpCancel() error {
   529  	out := &DumpCancelOut{}
   530  	return c.call("DumpCancel", DumpCancelIn{}, out)
   531  }
   532  
   533  // ListTargets returns the current list of debug targets.
   534  func (c *RPCClient) ListTargets() ([]api.Target, error) {
   535  	out := &ListTargetsOut{}
   536  	err := c.call("ListTargets", ListTargetsIn{}, out)
   537  	return out.Targets, err
   538  }
   539  
   540  // FollowExec enabled or disabled follow exec mode. When follow exec is
   541  // enabled Delve will automatically attach to new subprocesses with a
   542  // command line matched by regex, if regex is nil all new subprocesses are
   543  // automatically debugged.
   544  func (c *RPCClient) FollowExec(v bool, regex string) error {
   545  	out := &FollowExecOut{}
   546  	err := c.call("FollowExec", FollowExecIn{Enable: v, Regex: regex}, out)
   547  	return err
   548  }
   549  
   550  // FollowExecEnabled returns true if follow exec mode is enabled.
   551  func (c *RPCClient) FollowExecEnabled() bool {
   552  	out := &FollowExecEnabledOut{}
   553  	_ = c.call("FollowExecEnabled", FollowExecEnabledIn{}, out)
   554  	return out.Enabled
   555  }
   556  
   557  func (c *RPCClient) SetDebugInfoDirectories(v []string) error {
   558  	return c.call("DebugInfoDirectories", DebugInfoDirectoriesIn{Set: true, List: v}, &DebugInfoDirectoriesOut{})
   559  }
   560  
   561  func (c *RPCClient) GetDebugInfoDirectories() ([]string, error) {
   562  	out := &DebugInfoDirectoriesOut{}
   563  	err := c.call("DebugInfoDirectories", DebugInfoDirectoriesIn{Set: false, List: nil}, out)
   564  	return out.List, err
   565  }
   566  
   567  func (c *RPCClient) call(method string, args, reply interface{}) error {
   568  	return c.client.Call("RPCServer."+method, args, reply)
   569  }
   570  
   571  func (c *RPCClient) CallAPI(method string, args, reply interface{}) error {
   572  	return c.call(method, args, reply)
   573  }