github.com/neilgarb/delve@v1.9.2-nobreaks/service/rpc2/server.go (about)

     1  package rpc2
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"sort"
     7  	"time"
     8  
     9  	"github.com/go-delve/delve/pkg/dwarf/op"
    10  	"github.com/go-delve/delve/pkg/proc"
    11  	"github.com/go-delve/delve/service"
    12  	"github.com/go-delve/delve/service/api"
    13  	"github.com/go-delve/delve/service/debugger"
    14  )
    15  
    16  type RPCServer struct {
    17  	// config is all the information necessary to start the debugger and server.
    18  	config *service.Config
    19  	// debugger is a debugger service.
    20  	debugger *debugger.Debugger
    21  }
    22  
    23  func NewServer(config *service.Config, debugger *debugger.Debugger) *RPCServer {
    24  	return &RPCServer{config, debugger}
    25  }
    26  
    27  type ProcessPidIn struct {
    28  }
    29  
    30  type ProcessPidOut struct {
    31  	Pid int
    32  }
    33  
    34  // ProcessPid returns the pid of the process we are debugging.
    35  func (s *RPCServer) ProcessPid(arg ProcessPidIn, out *ProcessPidOut) error {
    36  	out.Pid = s.debugger.ProcessPid()
    37  	return nil
    38  }
    39  
    40  type LastModifiedIn struct {
    41  }
    42  
    43  type LastModifiedOut struct {
    44  	Time time.Time
    45  }
    46  
    47  func (s *RPCServer) LastModified(arg LastModifiedIn, out *LastModifiedOut) error {
    48  	out.Time = s.debugger.LastModified()
    49  	return nil
    50  }
    51  
    52  type DetachIn struct {
    53  	Kill bool
    54  }
    55  
    56  type DetachOut struct {
    57  }
    58  
    59  // Detach detaches the debugger, optionally killing the process.
    60  func (s *RPCServer) Detach(arg DetachIn, out *DetachOut) error {
    61  	return s.debugger.Detach(arg.Kill)
    62  }
    63  
    64  type RestartIn struct {
    65  	// Position to restart from, if it starts with 'c' it's a checkpoint ID,
    66  	// otherwise it's an event number. Only valid for recorded targets.
    67  	Position string
    68  
    69  	// ResetArgs tell whether NewArgs and NewRedirects should take effect.
    70  	ResetArgs bool
    71  	// NewArgs are arguments to launch a new process.  They replace only the
    72  	// argv[1] and later. Argv[0] cannot be changed.
    73  	NewArgs []string
    74  
    75  	// When Rerecord is set the target will be rerecorded
    76  	Rerecord bool
    77  
    78  	// When Rebuild is set the process will be build again
    79  	Rebuild bool
    80  
    81  	NewRedirects [3]string
    82  }
    83  
    84  type RestartOut struct {
    85  	DiscardedBreakpoints []api.DiscardedBreakpoint
    86  }
    87  
    88  // Restart restarts program.
    89  func (s *RPCServer) Restart(arg RestartIn, cb service.RPCCallback) {
    90  	close(cb.SetupDoneChan())
    91  	if s.config.Debugger.AttachPid != 0 {
    92  		cb.Return(nil, errors.New("cannot restart process Delve did not create"))
    93  		return
    94  	}
    95  	var out RestartOut
    96  	var err error
    97  	out.DiscardedBreakpoints, err = s.debugger.Restart(arg.Rerecord, arg.Position, arg.ResetArgs, arg.NewArgs, arg.NewRedirects, arg.Rebuild)
    98  	cb.Return(out, err)
    99  }
   100  
   101  type StateIn struct {
   102  	// If NonBlocking is true State will return immediately even if the target process is running.
   103  	NonBlocking bool
   104  }
   105  
   106  type StateOut struct {
   107  	State *api.DebuggerState
   108  }
   109  
   110  // State returns the current debugger state.
   111  func (s *RPCServer) State(arg StateIn, cb service.RPCCallback) {
   112  	close(cb.SetupDoneChan())
   113  	var out StateOut
   114  	st, err := s.debugger.State(arg.NonBlocking)
   115  	if err != nil {
   116  		cb.Return(nil, err)
   117  		return
   118  	}
   119  	out.State = st
   120  	cb.Return(out, nil)
   121  }
   122  
   123  type CommandOut struct {
   124  	State api.DebuggerState
   125  }
   126  
   127  // Command interrupts, continues and steps through the program.
   128  func (s *RPCServer) Command(command api.DebuggerCommand, cb service.RPCCallback) {
   129  	st, err := s.debugger.Command(&command, cb.SetupDoneChan())
   130  	if err != nil {
   131  		cb.Return(nil, err)
   132  		return
   133  	}
   134  	var out CommandOut
   135  	out.State = *st
   136  	cb.Return(out, nil)
   137  }
   138  
   139  type GetBufferedTracepointsIn struct {
   140  }
   141  
   142  type GetBufferedTracepointsOut struct {
   143  	TracepointResults []api.TracepointResult
   144  }
   145  
   146  func (s *RPCServer) GetBufferedTracepoints(arg GetBufferedTracepointsIn, out *GetBufferedTracepointsOut) error {
   147  	out.TracepointResults = s.debugger.GetBufferedTracepoints()
   148  	return nil
   149  }
   150  
   151  type GetBreakpointIn struct {
   152  	Id   int
   153  	Name string
   154  }
   155  
   156  type GetBreakpointOut struct {
   157  	Breakpoint api.Breakpoint
   158  }
   159  
   160  // GetBreakpoint gets a breakpoint by Name (if Name is not an empty string) or by ID.
   161  func (s *RPCServer) GetBreakpoint(arg GetBreakpointIn, out *GetBreakpointOut) error {
   162  	var bp *api.Breakpoint
   163  	if arg.Name != "" {
   164  		bp = s.debugger.FindBreakpointByName(arg.Name)
   165  		if bp == nil {
   166  			return fmt.Errorf("no breakpoint with name %s", arg.Name)
   167  		}
   168  	} else {
   169  		bp = s.debugger.FindBreakpoint(arg.Id)
   170  		if bp == nil {
   171  			return fmt.Errorf("no breakpoint with id %d", arg.Id)
   172  		}
   173  	}
   174  	out.Breakpoint = *bp
   175  	return nil
   176  }
   177  
   178  type StacktraceIn struct {
   179  	Id     int
   180  	Depth  int
   181  	Full   bool
   182  	Defers bool // read deferred functions (equivalent to passing StacktraceReadDefers in Opts)
   183  	Opts   api.StacktraceOptions
   184  	Cfg    *api.LoadConfig
   185  }
   186  
   187  type StacktraceOut struct {
   188  	Locations []api.Stackframe
   189  }
   190  
   191  // Stacktrace returns stacktrace of goroutine Id up to the specified Depth.
   192  //
   193  // If Full is set it will also the variable of all local variables
   194  // and function arguments of all stack frames.
   195  func (s *RPCServer) Stacktrace(arg StacktraceIn, out *StacktraceOut) error {
   196  	cfg := arg.Cfg
   197  	if cfg == nil && arg.Full {
   198  		cfg = &api.LoadConfig{FollowPointers: true, MaxVariableRecurse: 1, MaxStringLen: 64, MaxArrayValues: 64, MaxStructFields: -1}
   199  	}
   200  	if arg.Defers {
   201  		arg.Opts |= api.StacktraceReadDefers
   202  	}
   203  	var err error
   204  	rawlocs, err := s.debugger.Stacktrace(arg.Id, arg.Depth, arg.Opts)
   205  	if err != nil {
   206  		return err
   207  	}
   208  	out.Locations, err = s.debugger.ConvertStacktrace(rawlocs, api.LoadConfigToProc(cfg))
   209  	return err
   210  }
   211  
   212  type AncestorsIn struct {
   213  	GoroutineID  int
   214  	NumAncestors int
   215  	Depth        int
   216  }
   217  
   218  type AncestorsOut struct {
   219  	Ancestors []api.Ancestor
   220  }
   221  
   222  // Ancestors returns the stacktraces for the ancestors of a goroutine.
   223  func (s *RPCServer) Ancestors(arg AncestorsIn, out *AncestorsOut) error {
   224  	var err error
   225  	out.Ancestors, err = s.debugger.Ancestors(arg.GoroutineID, arg.NumAncestors, arg.Depth)
   226  	return err
   227  }
   228  
   229  type ListBreakpointsIn struct {
   230  	All bool
   231  }
   232  
   233  type ListBreakpointsOut struct {
   234  	Breakpoints []*api.Breakpoint
   235  }
   236  
   237  // ListBreakpoints gets all breakpoints.
   238  func (s *RPCServer) ListBreakpoints(arg ListBreakpointsIn, out *ListBreakpointsOut) error {
   239  	out.Breakpoints = s.debugger.Breakpoints(arg.All)
   240  	return nil
   241  }
   242  
   243  type CreateBreakpointIn struct {
   244  	Breakpoint api.Breakpoint
   245  }
   246  
   247  type CreateBreakpointOut struct {
   248  	Breakpoint api.Breakpoint
   249  }
   250  
   251  // CreateBreakpoint creates a new breakpoint. The client is expected to populate `CreateBreakpointIn`
   252  // with an `api.Breakpoint` struct describing where to set the breakpoing. For more information on
   253  // how to properly request a breakpoint via the `api.Breakpoint` struct see the documentation for
   254  // `debugger.CreateBreakpoint` here: https://pkg.go.dev/github.com/go-delve/delve/service/debugger#Debugger.CreateBreakpoint.
   255  func (s *RPCServer) CreateBreakpoint(arg CreateBreakpointIn, out *CreateBreakpointOut) error {
   256  	if err := api.ValidBreakpointName(arg.Breakpoint.Name); err != nil {
   257  		return err
   258  	}
   259  	createdbp, err := s.debugger.CreateBreakpoint(&arg.Breakpoint)
   260  	if err != nil {
   261  		return err
   262  	}
   263  	out.Breakpoint = *createdbp
   264  	return nil
   265  }
   266  
   267  type CreateEBPFTracepointIn struct {
   268  	FunctionName string
   269  }
   270  
   271  type CreateEBPFTracepointOut struct {
   272  	Breakpoint api.Breakpoint
   273  }
   274  
   275  func (s *RPCServer) CreateEBPFTracepoint(arg CreateEBPFTracepointIn, out *CreateEBPFTracepointOut) error {
   276  	return s.debugger.CreateEBPFTracepoint(arg.FunctionName)
   277  }
   278  
   279  type ClearBreakpointIn struct {
   280  	Id   int
   281  	Name string
   282  }
   283  
   284  type ClearBreakpointOut struct {
   285  	Breakpoint *api.Breakpoint
   286  }
   287  
   288  // ClearBreakpoint deletes a breakpoint by Name (if Name is not an
   289  // empty string) or by ID.
   290  func (s *RPCServer) ClearBreakpoint(arg ClearBreakpointIn, out *ClearBreakpointOut) error {
   291  	var bp *api.Breakpoint
   292  	if arg.Name != "" {
   293  		bp = s.debugger.FindBreakpointByName(arg.Name)
   294  		if bp == nil {
   295  			return fmt.Errorf("no breakpoint with name %s", arg.Name)
   296  		}
   297  	} else {
   298  		bp = s.debugger.FindBreakpoint(arg.Id)
   299  		if bp == nil {
   300  			return fmt.Errorf("no breakpoint with id %d", arg.Id)
   301  		}
   302  	}
   303  	deleted, err := s.debugger.ClearBreakpoint(bp)
   304  	if err != nil {
   305  		return err
   306  	}
   307  	out.Breakpoint = deleted
   308  	return nil
   309  }
   310  
   311  type ToggleBreakpointIn struct {
   312  	Id   int
   313  	Name string
   314  }
   315  
   316  type ToggleBreakpointOut struct {
   317  	Breakpoint *api.Breakpoint
   318  }
   319  
   320  // ToggleBreakpoint toggles on or off a breakpoint by Name (if Name is not an
   321  // empty string) or by ID.
   322  func (s *RPCServer) ToggleBreakpoint(arg ToggleBreakpointIn, out *ToggleBreakpointOut) error {
   323  	var bp *api.Breakpoint
   324  	if arg.Name != "" {
   325  		bp = s.debugger.FindBreakpointByName(arg.Name)
   326  		if bp == nil {
   327  			return fmt.Errorf("no breakpoint with name %s", arg.Name)
   328  		}
   329  	} else {
   330  		bp = s.debugger.FindBreakpoint(arg.Id)
   331  		if bp == nil {
   332  			return fmt.Errorf("no breakpoint with id %d", arg.Id)
   333  		}
   334  	}
   335  	bp.Disabled = !bp.Disabled
   336  	if err := api.ValidBreakpointName(bp.Name); err != nil {
   337  		return err
   338  	}
   339  	if err := s.debugger.AmendBreakpoint(bp); err != nil {
   340  		return err
   341  	}
   342  	out.Breakpoint = bp
   343  	return nil
   344  }
   345  
   346  type AmendBreakpointIn struct {
   347  	Breakpoint api.Breakpoint
   348  }
   349  
   350  type AmendBreakpointOut struct {
   351  }
   352  
   353  // AmendBreakpoint allows user to update an existing breakpoint
   354  // for example to change the information retrieved when the
   355  // breakpoint is hit or to change, add or remove the break condition.
   356  //
   357  // arg.Breakpoint.ID must be a valid breakpoint ID
   358  func (s *RPCServer) AmendBreakpoint(arg AmendBreakpointIn, out *AmendBreakpointOut) error {
   359  	if err := api.ValidBreakpointName(arg.Breakpoint.Name); err != nil {
   360  		return err
   361  	}
   362  	return s.debugger.AmendBreakpoint(&arg.Breakpoint)
   363  }
   364  
   365  type CancelNextIn struct {
   366  }
   367  
   368  type CancelNextOut struct {
   369  }
   370  
   371  func (s *RPCServer) CancelNext(arg CancelNextIn, out *CancelNextOut) error {
   372  	return s.debugger.CancelNext()
   373  }
   374  
   375  type ListThreadsIn struct {
   376  }
   377  
   378  type ListThreadsOut struct {
   379  	Threads []*api.Thread
   380  }
   381  
   382  // ListThreads lists all threads.
   383  func (s *RPCServer) ListThreads(arg ListThreadsIn, out *ListThreadsOut) (err error) {
   384  	threads, err := s.debugger.Threads()
   385  	if err != nil {
   386  		return err
   387  	}
   388  	s.debugger.LockTarget()
   389  	defer s.debugger.UnlockTarget()
   390  	out.Threads = api.ConvertThreads(threads, s.debugger.ConvertThreadBreakpoint)
   391  	return nil
   392  }
   393  
   394  type GetThreadIn struct {
   395  	Id int
   396  }
   397  
   398  type GetThreadOut struct {
   399  	Thread *api.Thread
   400  }
   401  
   402  // GetThread gets a thread by its ID.
   403  func (s *RPCServer) GetThread(arg GetThreadIn, out *GetThreadOut) error {
   404  	t, err := s.debugger.FindThread(arg.Id)
   405  	if err != nil {
   406  		return err
   407  	}
   408  	if t == nil {
   409  		return fmt.Errorf("no thread with id %d", arg.Id)
   410  	}
   411  	s.debugger.LockTarget()
   412  	defer s.debugger.UnlockTarget()
   413  	out.Thread = api.ConvertThread(t, s.debugger.ConvertThreadBreakpoint(t))
   414  	return nil
   415  }
   416  
   417  type ListPackageVarsIn struct {
   418  	Filter string
   419  	Cfg    api.LoadConfig
   420  }
   421  
   422  type ListPackageVarsOut struct {
   423  	Variables []api.Variable
   424  }
   425  
   426  // ListPackageVars lists all package variables in the context of the current thread.
   427  func (s *RPCServer) ListPackageVars(arg ListPackageVarsIn, out *ListPackageVarsOut) error {
   428  	vars, err := s.debugger.PackageVariables(arg.Filter, *api.LoadConfigToProc(&arg.Cfg))
   429  	if err != nil {
   430  		return err
   431  	}
   432  	out.Variables = api.ConvertVars(vars)
   433  	return nil
   434  }
   435  
   436  type ListRegistersIn struct {
   437  	ThreadID  int
   438  	IncludeFp bool
   439  	Scope     *api.EvalScope
   440  }
   441  
   442  type ListRegistersOut struct {
   443  	Registers string
   444  	Regs      api.Registers
   445  }
   446  
   447  // ListRegisters lists registers and their values.
   448  // If ListRegistersIn.Scope is not nil the registers of that eval scope will
   449  // be returned, otherwise ListRegistersIn.ThreadID will be used.
   450  func (s *RPCServer) ListRegisters(arg ListRegistersIn, out *ListRegistersOut) error {
   451  	if arg.ThreadID == 0 && arg.Scope == nil {
   452  		state, err := s.debugger.State(false)
   453  		if err != nil {
   454  			return err
   455  		}
   456  		arg.ThreadID = state.CurrentThread.ID
   457  	}
   458  
   459  	var regs *op.DwarfRegisters
   460  	var err error
   461  
   462  	if arg.Scope != nil {
   463  		regs, err = s.debugger.ScopeRegisters(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.IncludeFp)
   464  	} else {
   465  		regs, err = s.debugger.ThreadRegisters(arg.ThreadID, arg.IncludeFp)
   466  	}
   467  	if err != nil {
   468  		return err
   469  	}
   470  	out.Regs = api.ConvertRegisters(regs, s.debugger.DwarfRegisterToString, arg.IncludeFp)
   471  	out.Registers = out.Regs.String()
   472  
   473  	return nil
   474  }
   475  
   476  type ListLocalVarsIn struct {
   477  	Scope api.EvalScope
   478  	Cfg   api.LoadConfig
   479  }
   480  
   481  type ListLocalVarsOut struct {
   482  	Variables []api.Variable
   483  }
   484  
   485  // ListLocalVars lists all local variables in scope.
   486  func (s *RPCServer) ListLocalVars(arg ListLocalVarsIn, out *ListLocalVarsOut) error {
   487  	vars, err := s.debugger.LocalVariables(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, *api.LoadConfigToProc(&arg.Cfg))
   488  	if err != nil {
   489  		return err
   490  	}
   491  	out.Variables = api.ConvertVars(vars)
   492  	return nil
   493  }
   494  
   495  type ListFunctionArgsIn struct {
   496  	Scope api.EvalScope
   497  	Cfg   api.LoadConfig
   498  }
   499  
   500  type ListFunctionArgsOut struct {
   501  	Args []api.Variable
   502  }
   503  
   504  // ListFunctionArgs lists all arguments to the current function
   505  func (s *RPCServer) ListFunctionArgs(arg ListFunctionArgsIn, out *ListFunctionArgsOut) error {
   506  	vars, err := s.debugger.FunctionArguments(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, *api.LoadConfigToProc(&arg.Cfg))
   507  	if err != nil {
   508  		return err
   509  	}
   510  	out.Args = api.ConvertVars(vars)
   511  	return nil
   512  }
   513  
   514  type EvalIn struct {
   515  	Scope api.EvalScope
   516  	Expr  string
   517  	Cfg   *api.LoadConfig
   518  }
   519  
   520  type EvalOut struct {
   521  	Variable *api.Variable
   522  }
   523  
   524  // Eval returns a variable in the specified context.
   525  //
   526  // See https://github.com/go-delve/delve/blob/master/Documentation/cli/expr.md
   527  // for a description of acceptable values of arg.Expr.
   528  func (s *RPCServer) Eval(arg EvalIn, out *EvalOut) error {
   529  	cfg := arg.Cfg
   530  	if cfg == nil {
   531  		cfg = &api.LoadConfig{FollowPointers: true, MaxVariableRecurse: 1, MaxStringLen: 64, MaxArrayValues: 64, MaxStructFields: -1}
   532  	}
   533  	v, err := s.debugger.EvalVariableInScope(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.Expr, *api.LoadConfigToProc(cfg))
   534  	if err != nil {
   535  		return err
   536  	}
   537  	out.Variable = api.ConvertVar(v)
   538  	return nil
   539  }
   540  
   541  type SetIn struct {
   542  	Scope  api.EvalScope
   543  	Symbol string
   544  	Value  string
   545  }
   546  
   547  type SetOut struct {
   548  }
   549  
   550  // Set sets the value of a variable. Only numerical types and
   551  // pointers are currently supported.
   552  func (s *RPCServer) Set(arg SetIn, out *SetOut) error {
   553  	return s.debugger.SetVariableInScope(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.Symbol, arg.Value)
   554  }
   555  
   556  type ListSourcesIn struct {
   557  	Filter string
   558  }
   559  
   560  type ListSourcesOut struct {
   561  	Sources []string
   562  }
   563  
   564  // ListSources lists all source files in the process matching filter.
   565  func (s *RPCServer) ListSources(arg ListSourcesIn, out *ListSourcesOut) error {
   566  	ss, err := s.debugger.Sources(arg.Filter)
   567  	if err != nil {
   568  		return err
   569  	}
   570  	out.Sources = ss
   571  	return nil
   572  }
   573  
   574  type ListFunctionsIn struct {
   575  	Filter string
   576  }
   577  
   578  type ListFunctionsOut struct {
   579  	Funcs []string
   580  }
   581  
   582  // ListFunctions lists all functions in the process matching filter.
   583  func (s *RPCServer) ListFunctions(arg ListFunctionsIn, out *ListFunctionsOut) error {
   584  	fns, err := s.debugger.Functions(arg.Filter)
   585  	if err != nil {
   586  		return err
   587  	}
   588  	out.Funcs = fns
   589  	return nil
   590  }
   591  
   592  type ListTypesIn struct {
   593  	Filter string
   594  }
   595  
   596  type ListTypesOut struct {
   597  	Types []string
   598  }
   599  
   600  // ListTypes lists all types in the process matching filter.
   601  func (s *RPCServer) ListTypes(arg ListTypesIn, out *ListTypesOut) error {
   602  	tps, err := s.debugger.Types(arg.Filter)
   603  	if err != nil {
   604  		return err
   605  	}
   606  	out.Types = tps
   607  	return nil
   608  }
   609  
   610  type ListGoroutinesIn struct {
   611  	Start int
   612  	Count int
   613  
   614  	Filters []api.ListGoroutinesFilter
   615  	api.GoroutineGroupingOptions
   616  }
   617  
   618  type ListGoroutinesOut struct {
   619  	Goroutines    []*api.Goroutine
   620  	Nextg         int
   621  	Groups        []api.GoroutineGroup
   622  	TooManyGroups bool
   623  }
   624  
   625  // ListGoroutines lists all goroutines.
   626  // If Count is specified ListGoroutines will return at the first Count
   627  // goroutines and an index in Nextg, that can be passed as the Start
   628  // parameter, to get more goroutines from ListGoroutines.
   629  // Passing a value of Start that wasn't returned by ListGoroutines will skip
   630  // an undefined number of goroutines.
   631  //
   632  // If arg.Filters are specified the list of returned goroutines is filtered
   633  // applying the specified filters.
   634  // For example:
   635  //
   636  //	ListGoroutinesFilter{ Kind: ListGoroutinesFilterUserLoc, Negated: false, Arg: "afile.go" }
   637  //
   638  // will only return goroutines whose UserLoc contains "afile.go" as a substring.
   639  // More specifically a goroutine matches a location filter if the specified
   640  // location, formatted like this:
   641  //
   642  //	filename:lineno in function
   643  //
   644  // contains Arg[0] as a substring.
   645  //
   646  // Filters can also be applied to goroutine labels:
   647  //
   648  //	ListGoroutineFilter{ Kind: ListGoroutinesFilterLabel, Negated: false, Arg: "key=value" }
   649  //
   650  // this filter will only return goroutines that have a key=value label.
   651  //
   652  // If arg.GroupBy is not GoroutineFieldNone then the goroutines will
   653  // be grouped with the specified criterion.
   654  // If the value of arg.GroupBy is GoroutineLabel goroutines will
   655  // be grouped by the value of the label with key GroupByKey.
   656  // For each group a maximum of MaxExamples example goroutines are
   657  // returned, as well as the total number of goroutines in the group.
   658  func (s *RPCServer) ListGoroutines(arg ListGoroutinesIn, out *ListGoroutinesOut) error {
   659  	//TODO(aarzilli): if arg contains a running goroutines filter (not negated)
   660  	// and start == 0 and count == 0 then we can optimize this by just looking
   661  	// at threads directly.
   662  	gs, nextg, err := s.debugger.Goroutines(arg.Start, arg.Count)
   663  	if err != nil {
   664  		return err
   665  	}
   666  	gs = s.debugger.FilterGoroutines(gs, arg.Filters)
   667  	gs, out.Groups, out.TooManyGroups = s.debugger.GroupGoroutines(gs, &arg.GoroutineGroupingOptions)
   668  	s.debugger.LockTarget()
   669  	defer s.debugger.UnlockTarget()
   670  	out.Goroutines = api.ConvertGoroutines(s.debugger.Target(), gs)
   671  	out.Nextg = nextg
   672  	return nil
   673  }
   674  
   675  type AttachedToExistingProcessIn struct {
   676  }
   677  
   678  type AttachedToExistingProcessOut struct {
   679  	Answer bool
   680  }
   681  
   682  // AttachedToExistingProcess returns whether we attached to a running process or not
   683  func (c *RPCServer) AttachedToExistingProcess(arg AttachedToExistingProcessIn, out *AttachedToExistingProcessOut) error {
   684  	if c.config.Debugger.AttachPid != 0 {
   685  		out.Answer = true
   686  	}
   687  	return nil
   688  }
   689  
   690  type FindLocationIn struct {
   691  	Scope                     api.EvalScope
   692  	Loc                       string
   693  	IncludeNonExecutableLines bool
   694  
   695  	// SubstitutePathRules is a slice of source code path substitution rules,
   696  	// the first entry of each pair is the path of a directory as it appears in
   697  	// the executable file (i.e. the location of a source file when the program
   698  	// was compiled), the second entry of each pair is the location of the same
   699  	// directory on the client system.
   700  	SubstitutePathRules [][2]string
   701  }
   702  
   703  type FindLocationOut struct {
   704  	Locations []api.Location
   705  }
   706  
   707  // FindLocation returns concrete location information described by a location expression.
   708  //
   709  //	loc ::= <filename>:<line> | <function>[:<line>] | /<regex>/ | (+|-)<offset> | <line> | *<address>
   710  //	* <filename> can be the full path of a file or just a suffix
   711  //	* <function> ::= <package>.<receiver type>.<name> | <package>.(*<receiver type>).<name> | <receiver type>.<name> | <package>.<name> | (*<receiver type>).<name> | <name>
   712  //	  <function> must be unambiguous
   713  //	* /<regex>/ will return a location for each function matched by regex
   714  //	* +<offset> returns a location for the line that is <offset> lines after the current line
   715  //	* -<offset> returns a location for the line that is <offset> lines before the current line
   716  //	* <line> returns a location for a line in the current file
   717  //	* *<address> returns the location corresponding to the specified address
   718  //
   719  // NOTE: this function does not actually set breakpoints.
   720  func (c *RPCServer) FindLocation(arg FindLocationIn, out *FindLocationOut) error {
   721  	var err error
   722  	out.Locations, err = c.debugger.FindLocation(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.Loc, arg.IncludeNonExecutableLines, arg.SubstitutePathRules)
   723  	return err
   724  }
   725  
   726  type DisassembleIn struct {
   727  	Scope          api.EvalScope
   728  	StartPC, EndPC uint64
   729  	Flavour        api.AssemblyFlavour
   730  }
   731  
   732  type DisassembleOut struct {
   733  	Disassemble api.AsmInstructions
   734  }
   735  
   736  // Disassemble code.
   737  //
   738  // If both StartPC and EndPC are non-zero the specified range will be disassembled, otherwise the function containing StartPC will be disassembled.
   739  //
   740  // Scope is used to mark the instruction the specified goroutine is stopped at.
   741  //
   742  // Disassemble will also try to calculate the destination address of an absolute indirect CALL if it happens to be the instruction the selected goroutine is stopped at.
   743  func (c *RPCServer) Disassemble(arg DisassembleIn, out *DisassembleOut) error {
   744  	var err error
   745  	insts, err := c.debugger.Disassemble(arg.Scope.GoroutineID, arg.StartPC, arg.EndPC)
   746  	if err != nil {
   747  		return err
   748  	}
   749  	out.Disassemble = make(api.AsmInstructions, len(insts))
   750  	for i := range insts {
   751  		out.Disassemble[i] = api.ConvertAsmInstruction(insts[i], c.debugger.AsmInstructionText(&insts[i], proc.AssemblyFlavour(arg.Flavour)))
   752  	}
   753  	return nil
   754  }
   755  
   756  type RecordedIn struct {
   757  }
   758  
   759  type RecordedOut struct {
   760  	Recorded       bool
   761  	TraceDirectory string
   762  }
   763  
   764  func (s *RPCServer) Recorded(arg RecordedIn, out *RecordedOut) error {
   765  	out.Recorded, out.TraceDirectory = s.debugger.Recorded()
   766  	return nil
   767  }
   768  
   769  type CheckpointIn struct {
   770  	Where string
   771  }
   772  
   773  type CheckpointOut struct {
   774  	ID int
   775  }
   776  
   777  func (s *RPCServer) Checkpoint(arg CheckpointIn, out *CheckpointOut) error {
   778  	var err error
   779  	out.ID, err = s.debugger.Checkpoint(arg.Where)
   780  	return err
   781  }
   782  
   783  type ListCheckpointsIn struct {
   784  }
   785  
   786  type ListCheckpointsOut struct {
   787  	Checkpoints []api.Checkpoint
   788  }
   789  
   790  func (s *RPCServer) ListCheckpoints(arg ListCheckpointsIn, out *ListCheckpointsOut) error {
   791  	var err error
   792  	cps, err := s.debugger.Checkpoints()
   793  	if err != nil {
   794  		return err
   795  	}
   796  	out.Checkpoints = make([]api.Checkpoint, len(cps))
   797  	for i := range cps {
   798  		out.Checkpoints[i] = api.Checkpoint(cps[i])
   799  	}
   800  	return nil
   801  }
   802  
   803  type ClearCheckpointIn struct {
   804  	ID int
   805  }
   806  
   807  type ClearCheckpointOut struct {
   808  }
   809  
   810  func (s *RPCServer) ClearCheckpoint(arg ClearCheckpointIn, out *ClearCheckpointOut) error {
   811  	return s.debugger.ClearCheckpoint(arg.ID)
   812  }
   813  
   814  type IsMulticlientIn struct {
   815  }
   816  
   817  type IsMulticlientOut struct {
   818  	// IsMulticlient returns true if the headless instance was started with --accept-multiclient
   819  	IsMulticlient bool
   820  }
   821  
   822  func (s *RPCServer) IsMulticlient(arg IsMulticlientIn, out *IsMulticlientOut) error {
   823  	*out = IsMulticlientOut{
   824  		IsMulticlient: s.config.AcceptMulti,
   825  	}
   826  	return nil
   827  }
   828  
   829  // FunctionReturnLocationsIn holds arguments for the
   830  // FunctionReturnLocationsRPC call. It holds the name of
   831  // the function for which all return locations should be
   832  // given.
   833  type FunctionReturnLocationsIn struct {
   834  	// FnName is the name of the function for which all
   835  	// return locations should be given.
   836  	FnName string
   837  }
   838  
   839  // FunctionReturnLocationsOut holds the result of the FunctionReturnLocations
   840  // RPC call. It provides the list of addresses that the given function returns,
   841  // for example with a `RET` instruction or `CALL runtime.deferreturn`.
   842  type FunctionReturnLocationsOut struct {
   843  	// Addrs is the list of all locations where the given function returns.
   844  	Addrs []uint64
   845  }
   846  
   847  // FunctionReturnLocations is the implements the client call of the same name. Look at client documentation for more information.
   848  func (s *RPCServer) FunctionReturnLocations(in FunctionReturnLocationsIn, out *FunctionReturnLocationsOut) error {
   849  	addrs, err := s.debugger.FunctionReturnLocations(in.FnName)
   850  	if err != nil {
   851  		return err
   852  	}
   853  	*out = FunctionReturnLocationsOut{
   854  		Addrs: addrs,
   855  	}
   856  	return nil
   857  }
   858  
   859  // ListDynamicLibrariesIn holds the arguments of ListDynamicLibraries
   860  type ListDynamicLibrariesIn struct {
   861  }
   862  
   863  // ListDynamicLibrariesOut holds the return values of ListDynamicLibraries
   864  type ListDynamicLibrariesOut struct {
   865  	List []api.Image
   866  }
   867  
   868  func (s *RPCServer) ListDynamicLibraries(in ListDynamicLibrariesIn, out *ListDynamicLibrariesOut) error {
   869  	imgs := s.debugger.ListDynamicLibraries()
   870  	out.List = make([]api.Image, 0, len(imgs))
   871  	for i := range imgs {
   872  		out.List = append(out.List, api.ConvertImage(imgs[i]))
   873  	}
   874  	return nil
   875  }
   876  
   877  // ListPackagesBuildInfoIn holds the arguments of ListPackages.
   878  type ListPackagesBuildInfoIn struct {
   879  	IncludeFiles bool
   880  }
   881  
   882  // ListPackagesBuildInfoOut holds the return values of ListPackages.
   883  type ListPackagesBuildInfoOut struct {
   884  	List []api.PackageBuildInfo
   885  }
   886  
   887  // ListPackagesBuildInfo returns the list of packages used by the program along with
   888  // the directory where each package was compiled and optionally the list of
   889  // files constituting the package.
   890  // Note that the directory path is a best guess and may be wrong is a tool
   891  // other than cmd/go is used to perform the build.
   892  func (s *RPCServer) ListPackagesBuildInfo(in ListPackagesBuildInfoIn, out *ListPackagesBuildInfoOut) error {
   893  	pkgs := s.debugger.ListPackagesBuildInfo(in.IncludeFiles)
   894  	out.List = make([]api.PackageBuildInfo, 0, len(pkgs))
   895  	for _, pkg := range pkgs {
   896  		var files []string
   897  
   898  		if len(pkg.Files) > 0 {
   899  			files = make([]string, 0, len(pkg.Files))
   900  			for file := range pkg.Files {
   901  				files = append(files, file)
   902  			}
   903  		}
   904  
   905  		sort.Strings(files)
   906  
   907  		out.List = append(out.List, api.PackageBuildInfo{
   908  			ImportPath:    pkg.ImportPath,
   909  			DirectoryPath: pkg.DirectoryPath,
   910  			Files:         files,
   911  		})
   912  	}
   913  	return nil
   914  }
   915  
   916  // ExamineMemoryIn holds the arguments of ExamineMemory
   917  type ExamineMemoryIn struct {
   918  	Address uint64
   919  	Length  int
   920  }
   921  
   922  // ExaminedMemoryOut holds the return values of ExamineMemory
   923  type ExaminedMemoryOut struct {
   924  	Mem            []byte
   925  	IsLittleEndian bool
   926  }
   927  
   928  func (s *RPCServer) ExamineMemory(arg ExamineMemoryIn, out *ExaminedMemoryOut) error {
   929  	if arg.Length > 1000 {
   930  		return fmt.Errorf("len must be less than or equal to 1000")
   931  	}
   932  	Mem, err := s.debugger.ExamineMemory(arg.Address, arg.Length)
   933  	if err != nil {
   934  		return err
   935  	}
   936  
   937  	out.Mem = Mem
   938  	out.IsLittleEndian = true //TODO: get byte order from debugger.target.BinInfo().Arch
   939  
   940  	return nil
   941  }
   942  
   943  type StopRecordingIn struct {
   944  }
   945  
   946  type StopRecordingOut struct {
   947  }
   948  
   949  func (s *RPCServer) StopRecording(arg StopRecordingIn, cb service.RPCCallback) {
   950  	close(cb.SetupDoneChan())
   951  	var out StopRecordingOut
   952  	err := s.debugger.StopRecording()
   953  	if err != nil {
   954  		cb.Return(nil, err)
   955  		return
   956  	}
   957  	cb.Return(out, nil)
   958  }
   959  
   960  type DumpStartIn struct {
   961  	Destination string
   962  }
   963  
   964  type DumpStartOut struct {
   965  	State api.DumpState
   966  }
   967  
   968  // DumpStart starts a core dump to arg.Destination.
   969  func (s *RPCServer) DumpStart(arg DumpStartIn, out *DumpStartOut) error {
   970  	err := s.debugger.DumpStart(arg.Destination)
   971  	if err != nil {
   972  		return err
   973  	}
   974  	out.State = *api.ConvertDumpState(s.debugger.DumpWait(0))
   975  	return nil
   976  }
   977  
   978  type DumpWaitIn struct {
   979  	Wait int
   980  }
   981  
   982  type DumpWaitOut struct {
   983  	State api.DumpState
   984  }
   985  
   986  // DumpWait waits for the core dump to finish or for arg.Wait milliseconds.
   987  // Wait == 0 means return immediately.
   988  // Returns the core dump status
   989  func (s *RPCServer) DumpWait(arg DumpWaitIn, out *DumpWaitOut) error {
   990  	out.State = *api.ConvertDumpState(s.debugger.DumpWait(time.Duration(arg.Wait) * time.Millisecond))
   991  	return nil
   992  }
   993  
   994  type DumpCancelIn struct {
   995  }
   996  
   997  type DumpCancelOut struct {
   998  }
   999  
  1000  // DumpCancel cancels the core dump.
  1001  func (s *RPCServer) DumpCancel(arg DumpCancelIn, out *DumpCancelOut) error {
  1002  	return s.debugger.DumpCancel()
  1003  }
  1004  
  1005  type CreateWatchpointIn struct {
  1006  	Scope api.EvalScope
  1007  	Expr  string
  1008  	Type  api.WatchType
  1009  }
  1010  
  1011  type CreateWatchpointOut struct {
  1012  	*api.Breakpoint
  1013  }
  1014  
  1015  func (s *RPCServer) CreateWatchpoint(arg CreateWatchpointIn, out *CreateWatchpointOut) error {
  1016  	var err error
  1017  	out.Breakpoint, err = s.debugger.CreateWatchpoint(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.Expr, arg.Type)
  1018  	return err
  1019  }
  1020  
  1021  type BuildIDIn struct {
  1022  }
  1023  
  1024  type BuildIDOut struct {
  1025  	BuildID string
  1026  }
  1027  
  1028  func (s *RPCServer) BuildID(arg BuildIDIn, out *BuildIDOut) error {
  1029  	out.BuildID = s.debugger.BuildID()
  1030  	return nil
  1031  }