github.com/cnboonhan/delve@v0.0.0-20230908061759-363f2388c2fb/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     int64
   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  int64
   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  	LocExpr             string
   247  	SubstitutePathRules [][2]string
   248  	Suspended           bool
   249  }
   250  
   251  type CreateBreakpointOut struct {
   252  	Breakpoint api.Breakpoint
   253  }
   254  
   255  // CreateBreakpoint creates a new breakpoint. The client is expected to populate `CreateBreakpointIn`
   256  // with an `api.Breakpoint` struct describing where to set the breakpoint. For more information on
   257  // how to properly request a breakpoint via the `api.Breakpoint` struct see the documentation for
   258  // `debugger.CreateBreakpoint` here: https://pkg.go.dev/github.com/go-delve/delve/service/debugger#Debugger.CreateBreakpoint.
   259  func (s *RPCServer) CreateBreakpoint(arg CreateBreakpointIn, out *CreateBreakpointOut) error {
   260  	if err := api.ValidBreakpointName(arg.Breakpoint.Name); err != nil {
   261  		return err
   262  	}
   263  	createdbp, err := s.debugger.CreateBreakpoint(&arg.Breakpoint, arg.LocExpr, arg.SubstitutePathRules, arg.Suspended)
   264  	if err != nil {
   265  		return err
   266  	}
   267  	out.Breakpoint = *createdbp
   268  	return nil
   269  }
   270  
   271  type CreateEBPFTracepointIn struct {
   272  	FunctionName string
   273  }
   274  
   275  type CreateEBPFTracepointOut struct {
   276  	Breakpoint api.Breakpoint
   277  }
   278  
   279  func (s *RPCServer) CreateEBPFTracepoint(arg CreateEBPFTracepointIn, out *CreateEBPFTracepointOut) error {
   280  	return s.debugger.CreateEBPFTracepoint(arg.FunctionName)
   281  }
   282  
   283  type ClearBreakpointIn struct {
   284  	Id   int
   285  	Name string
   286  }
   287  
   288  type ClearBreakpointOut struct {
   289  	Breakpoint *api.Breakpoint
   290  }
   291  
   292  // ClearBreakpoint deletes a breakpoint by Name (if Name is not an
   293  // empty string) or by ID.
   294  func (s *RPCServer) ClearBreakpoint(arg ClearBreakpointIn, out *ClearBreakpointOut) error {
   295  	var bp *api.Breakpoint
   296  	if arg.Name != "" {
   297  		bp = s.debugger.FindBreakpointByName(arg.Name)
   298  		if bp == nil {
   299  			return fmt.Errorf("no breakpoint with name %s", arg.Name)
   300  		}
   301  	} else {
   302  		bp = s.debugger.FindBreakpoint(arg.Id)
   303  		if bp == nil {
   304  			return fmt.Errorf("no breakpoint with id %d", arg.Id)
   305  		}
   306  	}
   307  	deleted, err := s.debugger.ClearBreakpoint(bp)
   308  	if err != nil {
   309  		return err
   310  	}
   311  	out.Breakpoint = deleted
   312  	return nil
   313  }
   314  
   315  type ToggleBreakpointIn struct {
   316  	Id   int
   317  	Name string
   318  }
   319  
   320  type ToggleBreakpointOut struct {
   321  	Breakpoint *api.Breakpoint
   322  }
   323  
   324  // ToggleBreakpoint toggles on or off a breakpoint by Name (if Name is not an
   325  // empty string) or by ID.
   326  func (s *RPCServer) ToggleBreakpoint(arg ToggleBreakpointIn, out *ToggleBreakpointOut) error {
   327  	var bp *api.Breakpoint
   328  	if arg.Name != "" {
   329  		bp = s.debugger.FindBreakpointByName(arg.Name)
   330  		if bp == nil {
   331  			return fmt.Errorf("no breakpoint with name %s", arg.Name)
   332  		}
   333  	} else {
   334  		bp = s.debugger.FindBreakpoint(arg.Id)
   335  		if bp == nil {
   336  			return fmt.Errorf("no breakpoint with id %d", arg.Id)
   337  		}
   338  	}
   339  	bp.Disabled = !bp.Disabled
   340  	if err := api.ValidBreakpointName(bp.Name); err != nil {
   341  		return err
   342  	}
   343  	if err := s.debugger.AmendBreakpoint(bp); err != nil {
   344  		return err
   345  	}
   346  	out.Breakpoint = bp
   347  	return nil
   348  }
   349  
   350  type AmendBreakpointIn struct {
   351  	Breakpoint api.Breakpoint
   352  }
   353  
   354  type AmendBreakpointOut struct {
   355  }
   356  
   357  // AmendBreakpoint allows user to update an existing breakpoint
   358  // for example to change the information retrieved when the
   359  // breakpoint is hit or to change, add or remove the break condition.
   360  //
   361  // arg.Breakpoint.ID must be a valid breakpoint ID
   362  func (s *RPCServer) AmendBreakpoint(arg AmendBreakpointIn, out *AmendBreakpointOut) error {
   363  	if err := api.ValidBreakpointName(arg.Breakpoint.Name); err != nil {
   364  		return err
   365  	}
   366  	return s.debugger.AmendBreakpoint(&arg.Breakpoint)
   367  }
   368  
   369  type CancelNextIn struct {
   370  }
   371  
   372  type CancelNextOut struct {
   373  }
   374  
   375  func (s *RPCServer) CancelNext(arg CancelNextIn, out *CancelNextOut) error {
   376  	return s.debugger.CancelNext()
   377  }
   378  
   379  type ListThreadsIn struct {
   380  }
   381  
   382  type ListThreadsOut struct {
   383  	Threads []*api.Thread
   384  }
   385  
   386  // ListThreads lists all threads.
   387  func (s *RPCServer) ListThreads(arg ListThreadsIn, out *ListThreadsOut) (err error) {
   388  	threads, err := s.debugger.Threads()
   389  	if err != nil {
   390  		return err
   391  	}
   392  	s.debugger.LockTarget()
   393  	defer s.debugger.UnlockTarget()
   394  	out.Threads = api.ConvertThreads(threads, s.debugger.ConvertThreadBreakpoint)
   395  	return nil
   396  }
   397  
   398  type GetThreadIn struct {
   399  	Id int
   400  }
   401  
   402  type GetThreadOut struct {
   403  	Thread *api.Thread
   404  }
   405  
   406  // GetThread gets a thread by its ID.
   407  func (s *RPCServer) GetThread(arg GetThreadIn, out *GetThreadOut) error {
   408  	t, err := s.debugger.FindThread(arg.Id)
   409  	if err != nil {
   410  		return err
   411  	}
   412  	if t == nil {
   413  		return fmt.Errorf("no thread with id %d", arg.Id)
   414  	}
   415  	s.debugger.LockTarget()
   416  	defer s.debugger.UnlockTarget()
   417  	out.Thread = api.ConvertThread(t, s.debugger.ConvertThreadBreakpoint(t))
   418  	return nil
   419  }
   420  
   421  type ListPackageVarsIn struct {
   422  	Filter string
   423  	Cfg    api.LoadConfig
   424  }
   425  
   426  type ListPackageVarsOut struct {
   427  	Variables []api.Variable
   428  }
   429  
   430  // ListPackageVars lists all package variables in the context of the current thread.
   431  func (s *RPCServer) ListPackageVars(arg ListPackageVarsIn, out *ListPackageVarsOut) error {
   432  	vars, err := s.debugger.PackageVariables(arg.Filter, *api.LoadConfigToProc(&arg.Cfg))
   433  	if err != nil {
   434  		return err
   435  	}
   436  	out.Variables = api.ConvertVars(vars)
   437  	return nil
   438  }
   439  
   440  type ListRegistersIn struct {
   441  	ThreadID  int
   442  	IncludeFp bool
   443  	Scope     *api.EvalScope
   444  }
   445  
   446  type ListRegistersOut struct {
   447  	Registers string
   448  	Regs      api.Registers
   449  }
   450  
   451  // ListRegisters lists registers and their values.
   452  // If ListRegistersIn.Scope is not nil the registers of that eval scope will
   453  // be returned, otherwise ListRegistersIn.ThreadID will be used.
   454  func (s *RPCServer) ListRegisters(arg ListRegistersIn, out *ListRegistersOut) error {
   455  	if arg.ThreadID == 0 && arg.Scope == nil {
   456  		state, err := s.debugger.State(false)
   457  		if err != nil {
   458  			return err
   459  		}
   460  		arg.ThreadID = state.CurrentThread.ID
   461  	}
   462  
   463  	var regs *op.DwarfRegisters
   464  	var err error
   465  
   466  	if arg.Scope != nil {
   467  		regs, err = s.debugger.ScopeRegisters(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.IncludeFp)
   468  	} else {
   469  		regs, err = s.debugger.ThreadRegisters(arg.ThreadID, arg.IncludeFp)
   470  	}
   471  	if err != nil {
   472  		return err
   473  	}
   474  	out.Regs = api.ConvertRegisters(regs, s.debugger.DwarfRegisterToString, arg.IncludeFp)
   475  	out.Registers = out.Regs.String()
   476  
   477  	return nil
   478  }
   479  
   480  type ListLocalVarsIn struct {
   481  	Scope api.EvalScope
   482  	Cfg   api.LoadConfig
   483  }
   484  
   485  type ListLocalVarsOut struct {
   486  	Variables []api.Variable
   487  }
   488  
   489  // ListLocalVars lists all local variables in scope.
   490  func (s *RPCServer) ListLocalVars(arg ListLocalVarsIn, out *ListLocalVarsOut) error {
   491  	vars, err := s.debugger.LocalVariables(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, *api.LoadConfigToProc(&arg.Cfg))
   492  	if err != nil {
   493  		return err
   494  	}
   495  	out.Variables = api.ConvertVars(vars)
   496  	return nil
   497  }
   498  
   499  type ListFunctionArgsIn struct {
   500  	Scope api.EvalScope
   501  	Cfg   api.LoadConfig
   502  }
   503  
   504  type ListFunctionArgsOut struct {
   505  	Args []api.Variable
   506  }
   507  
   508  // ListFunctionArgs lists all arguments to the current function
   509  func (s *RPCServer) ListFunctionArgs(arg ListFunctionArgsIn, out *ListFunctionArgsOut) error {
   510  	vars, err := s.debugger.FunctionArguments(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, *api.LoadConfigToProc(&arg.Cfg))
   511  	if err != nil {
   512  		return err
   513  	}
   514  	out.Args = api.ConvertVars(vars)
   515  	return nil
   516  }
   517  
   518  type EvalIn struct {
   519  	Scope api.EvalScope
   520  	Expr  string
   521  	Cfg   *api.LoadConfig
   522  }
   523  
   524  type EvalOut struct {
   525  	Variable *api.Variable
   526  }
   527  
   528  // Eval returns a variable in the specified context.
   529  //
   530  // See https://github.com/go-delve/delve/blob/master/Documentation/cli/expr.md
   531  // for a description of acceptable values of arg.Expr.
   532  func (s *RPCServer) Eval(arg EvalIn, out *EvalOut) error {
   533  	cfg := arg.Cfg
   534  	if cfg == nil {
   535  		cfg = &api.LoadConfig{FollowPointers: true, MaxVariableRecurse: 1, MaxStringLen: 64, MaxArrayValues: 64, MaxStructFields: -1}
   536  	}
   537  	pcfg := *api.LoadConfigToProc(cfg)
   538  	v, err := s.debugger.EvalVariableInScope(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.Expr, pcfg)
   539  	if err != nil {
   540  		return err
   541  	}
   542  	out.Variable = api.ConvertVar(v)
   543  	return nil
   544  }
   545  
   546  type SetIn struct {
   547  	Scope  api.EvalScope
   548  	Symbol string
   549  	Value  string
   550  }
   551  
   552  type SetOut struct {
   553  }
   554  
   555  // Set sets the value of a variable. Only numerical types and
   556  // pointers are currently supported.
   557  func (s *RPCServer) Set(arg SetIn, out *SetOut) error {
   558  	return s.debugger.SetVariableInScope(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.Symbol, arg.Value)
   559  }
   560  
   561  type ListSourcesIn struct {
   562  	Filter string
   563  }
   564  
   565  type ListSourcesOut struct {
   566  	Sources []string
   567  }
   568  
   569  // ListSources lists all source files in the process matching filter.
   570  func (s *RPCServer) ListSources(arg ListSourcesIn, out *ListSourcesOut) error {
   571  	ss, err := s.debugger.Sources(arg.Filter)
   572  	if err != nil {
   573  		return err
   574  	}
   575  	out.Sources = ss
   576  	return nil
   577  }
   578  
   579  type ListFunctionsIn struct {
   580  	Filter string
   581  }
   582  
   583  type ListFunctionsOut struct {
   584  	Funcs []string
   585  }
   586  
   587  // ListFunctions lists all functions in the process matching filter.
   588  func (s *RPCServer) ListFunctions(arg ListFunctionsIn, out *ListFunctionsOut) error {
   589  	fns, err := s.debugger.Functions(arg.Filter)
   590  	if err != nil {
   591  		return err
   592  	}
   593  	out.Funcs = fns
   594  	return nil
   595  }
   596  
   597  type ListTypesIn struct {
   598  	Filter string
   599  }
   600  
   601  type ListTypesOut struct {
   602  	Types []string
   603  }
   604  
   605  // ListTypes lists all types in the process matching filter.
   606  func (s *RPCServer) ListTypes(arg ListTypesIn, out *ListTypesOut) error {
   607  	tps, err := s.debugger.Types(arg.Filter)
   608  	if err != nil {
   609  		return err
   610  	}
   611  	out.Types = tps
   612  	return nil
   613  }
   614  
   615  type ListGoroutinesIn struct {
   616  	Start int
   617  	Count int
   618  
   619  	Filters []api.ListGoroutinesFilter
   620  	api.GoroutineGroupingOptions
   621  
   622  	EvalScope *api.EvalScope
   623  }
   624  
   625  type ListGoroutinesOut struct {
   626  	Goroutines    []*api.Goroutine
   627  	Nextg         int
   628  	Groups        []api.GoroutineGroup
   629  	TooManyGroups bool
   630  }
   631  
   632  // ListGoroutines lists all goroutines.
   633  // If Count is specified ListGoroutines will return at the first Count
   634  // goroutines and an index in Nextg, that can be passed as the Start
   635  // parameter, to get more goroutines from ListGoroutines.
   636  // Passing a value of Start that wasn't returned by ListGoroutines will skip
   637  // an undefined number of goroutines.
   638  //
   639  // If arg.Filters are specified the list of returned goroutines is filtered
   640  // applying the specified filters.
   641  // For example:
   642  //
   643  //	ListGoroutinesFilter{ Kind: ListGoroutinesFilterUserLoc, Negated: false, Arg: "afile.go" }
   644  //
   645  // will only return goroutines whose UserLoc contains "afile.go" as a substring.
   646  // More specifically a goroutine matches a location filter if the specified
   647  // location, formatted like this:
   648  //
   649  //	filename:lineno in function
   650  //
   651  // contains Arg[0] as a substring.
   652  //
   653  // Filters can also be applied to goroutine labels:
   654  //
   655  //	ListGoroutineFilter{ Kind: ListGoroutinesFilterLabel, Negated: false, Arg: "key=value" }
   656  //
   657  // this filter will only return goroutines that have a key=value label.
   658  //
   659  // If arg.GroupBy is not GoroutineFieldNone then the goroutines will
   660  // be grouped with the specified criterion.
   661  // If the value of arg.GroupBy is GoroutineLabel goroutines will
   662  // be grouped by the value of the label with key GroupByKey.
   663  // For each group a maximum of MaxGroupMembers example goroutines are
   664  // returned, as well as the total number of goroutines in the group.
   665  func (s *RPCServer) ListGoroutines(arg ListGoroutinesIn, out *ListGoroutinesOut) error {
   666  	//TODO(aarzilli): if arg contains a running goroutines filter (not negated)
   667  	// and start == 0 and count == 0 then we can optimize this by just looking
   668  	// at threads directly.
   669  
   670  	var gs []*proc.G
   671  	var nextg int
   672  	var err error
   673  	var gsLoaded bool
   674  
   675  	for _, filter := range arg.Filters {
   676  		if filter.Kind == api.GoroutineWaitingOnChannel {
   677  			if filter.Negated {
   678  				return errors.New("channel filter can not be negated")
   679  			}
   680  			if arg.Count == 0 {
   681  				return errors.New("count == 0 not allowed with a channel filter")
   682  			}
   683  			if arg.EvalScope == nil {
   684  				return errors.New("channel filter without eval scope")
   685  			}
   686  			gs, err = s.debugger.ChanGoroutines(arg.EvalScope.GoroutineID, arg.EvalScope.Frame, arg.EvalScope.DeferredCall, filter.Arg, arg.Start, arg.Count)
   687  			if len(gs) == arg.Count {
   688  				nextg = arg.Start + len(gs)
   689  			} else {
   690  				nextg = -1
   691  			}
   692  			gsLoaded = true
   693  			break
   694  		}
   695  	}
   696  
   697  	if !gsLoaded {
   698  		gs, nextg, err = s.debugger.Goroutines(arg.Start, arg.Count)
   699  	}
   700  	if err != nil {
   701  		return err
   702  	}
   703  	gs = s.debugger.FilterGoroutines(gs, arg.Filters)
   704  	gs, out.Groups, out.TooManyGroups = s.debugger.GroupGoroutines(gs, &arg.GoroutineGroupingOptions)
   705  	s.debugger.LockTarget()
   706  	defer s.debugger.UnlockTarget()
   707  	out.Goroutines = api.ConvertGoroutines(s.debugger.Target(), gs)
   708  	out.Nextg = nextg
   709  	return nil
   710  }
   711  
   712  type AttachedToExistingProcessIn struct {
   713  }
   714  
   715  type AttachedToExistingProcessOut struct {
   716  	Answer bool
   717  }
   718  
   719  // AttachedToExistingProcess returns whether we attached to a running process or not
   720  func (s *RPCServer) AttachedToExistingProcess(arg AttachedToExistingProcessIn, out *AttachedToExistingProcessOut) error {
   721  	if s.config.Debugger.AttachPid != 0 {
   722  		out.Answer = true
   723  	}
   724  	return nil
   725  }
   726  
   727  type FindLocationIn struct {
   728  	Scope                     api.EvalScope
   729  	Loc                       string
   730  	IncludeNonExecutableLines bool
   731  
   732  	// SubstitutePathRules is a slice of source code path substitution rules,
   733  	// the first entry of each pair is the path of a directory as it appears in
   734  	// the executable file (i.e. the location of a source file when the program
   735  	// was compiled), the second entry of each pair is the location of the same
   736  	// directory on the client system.
   737  	SubstitutePathRules [][2]string
   738  }
   739  
   740  type FindLocationOut struct {
   741  	Locations         []api.Location
   742  	SubstituteLocExpr string // if this isn't an empty string it should be passed as the location expression for CreateBreakpoint instead of the original location expression
   743  }
   744  
   745  // FindLocation returns concrete location information described by a location expression.
   746  //
   747  //	loc ::= <filename>:<line> | <function>[:<line>] | /<regex>/ | (+|-)<offset> | <line> | *<address>
   748  //	* <filename> can be the full path of a file or just a suffix
   749  //	* <function> ::= <package>.<receiver type>.<name> | <package>.(*<receiver type>).<name> | <receiver type>.<name> | <package>.<name> | (*<receiver type>).<name> | <name>
   750  //	  <function> must be unambiguous
   751  //	* /<regex>/ will return a location for each function matched by regex
   752  //	* +<offset> returns a location for the line that is <offset> lines after the current line
   753  //	* -<offset> returns a location for the line that is <offset> lines before the current line
   754  //	* <line> returns a location for a line in the current file
   755  //	* *<address> returns the location corresponding to the specified address
   756  //
   757  // NOTE: this function does not actually set breakpoints.
   758  func (s *RPCServer) FindLocation(arg FindLocationIn, out *FindLocationOut) error {
   759  	var err error
   760  	out.Locations, out.SubstituteLocExpr, err = s.debugger.FindLocation(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.Loc, arg.IncludeNonExecutableLines, arg.SubstitutePathRules)
   761  	return err
   762  }
   763  
   764  type DisassembleIn struct {
   765  	Scope          api.EvalScope
   766  	StartPC, EndPC uint64
   767  	Flavour        api.AssemblyFlavour
   768  }
   769  
   770  type DisassembleOut struct {
   771  	Disassemble api.AsmInstructions
   772  }
   773  
   774  // Disassemble code.
   775  //
   776  // If both StartPC and EndPC are non-zero the specified range will be disassembled, otherwise the function containing StartPC will be disassembled.
   777  //
   778  // Scope is used to mark the instruction the specified goroutine is stopped at.
   779  //
   780  // 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.
   781  func (s *RPCServer) Disassemble(arg DisassembleIn, out *DisassembleOut) error {
   782  	var err error
   783  	insts, err := s.debugger.Disassemble(arg.Scope.GoroutineID, arg.StartPC, arg.EndPC)
   784  	if err != nil {
   785  		return err
   786  	}
   787  	out.Disassemble = make(api.AsmInstructions, len(insts))
   788  	for i := range insts {
   789  		out.Disassemble[i] = api.ConvertAsmInstruction(insts[i], s.debugger.AsmInstructionText(&insts[i], proc.AssemblyFlavour(arg.Flavour)))
   790  	}
   791  	return nil
   792  }
   793  
   794  type RecordedIn struct {
   795  }
   796  
   797  type RecordedOut struct {
   798  	Recorded       bool
   799  	TraceDirectory string
   800  }
   801  
   802  func (s *RPCServer) Recorded(arg RecordedIn, out *RecordedOut) error {
   803  	out.Recorded, out.TraceDirectory = s.debugger.Recorded()
   804  	return nil
   805  }
   806  
   807  type CheckpointIn struct {
   808  	Where string
   809  }
   810  
   811  type CheckpointOut struct {
   812  	ID int
   813  }
   814  
   815  func (s *RPCServer) Checkpoint(arg CheckpointIn, out *CheckpointOut) error {
   816  	var err error
   817  	out.ID, err = s.debugger.Checkpoint(arg.Where)
   818  	return err
   819  }
   820  
   821  type ListCheckpointsIn struct {
   822  }
   823  
   824  type ListCheckpointsOut struct {
   825  	Checkpoints []api.Checkpoint
   826  }
   827  
   828  func (s *RPCServer) ListCheckpoints(arg ListCheckpointsIn, out *ListCheckpointsOut) error {
   829  	var err error
   830  	cps, err := s.debugger.Checkpoints()
   831  	if err != nil {
   832  		return err
   833  	}
   834  	out.Checkpoints = make([]api.Checkpoint, len(cps))
   835  	for i := range cps {
   836  		out.Checkpoints[i] = api.Checkpoint(cps[i])
   837  	}
   838  	return nil
   839  }
   840  
   841  type ClearCheckpointIn struct {
   842  	ID int
   843  }
   844  
   845  type ClearCheckpointOut struct {
   846  }
   847  
   848  func (s *RPCServer) ClearCheckpoint(arg ClearCheckpointIn, out *ClearCheckpointOut) error {
   849  	return s.debugger.ClearCheckpoint(arg.ID)
   850  }
   851  
   852  type IsMulticlientIn struct {
   853  }
   854  
   855  type IsMulticlientOut struct {
   856  	// IsMulticlient returns true if the headless instance was started with --accept-multiclient
   857  	IsMulticlient bool
   858  }
   859  
   860  func (s *RPCServer) IsMulticlient(arg IsMulticlientIn, out *IsMulticlientOut) error {
   861  	*out = IsMulticlientOut{
   862  		IsMulticlient: s.config.AcceptMulti,
   863  	}
   864  	return nil
   865  }
   866  
   867  // FunctionReturnLocationsIn holds arguments for the
   868  // FunctionReturnLocationsRPC call. It holds the name of
   869  // the function for which all return locations should be
   870  // given.
   871  type FunctionReturnLocationsIn struct {
   872  	// FnName is the name of the function for which all
   873  	// return locations should be given.
   874  	FnName string
   875  }
   876  
   877  // FunctionReturnLocationsOut holds the result of the FunctionReturnLocations
   878  // RPC call. It provides the list of addresses that the given function returns,
   879  // for example with a `RET` instruction or `CALL runtime.deferreturn`.
   880  type FunctionReturnLocationsOut struct {
   881  	// Addrs is the list of all locations where the given function returns.
   882  	Addrs []uint64
   883  }
   884  
   885  // FunctionReturnLocations is the implements the client call of the same name. Look at client documentation for more information.
   886  func (s *RPCServer) FunctionReturnLocations(in FunctionReturnLocationsIn, out *FunctionReturnLocationsOut) error {
   887  	addrs, err := s.debugger.FunctionReturnLocations(in.FnName)
   888  	if err != nil {
   889  		return err
   890  	}
   891  	*out = FunctionReturnLocationsOut{
   892  		Addrs: addrs,
   893  	}
   894  	return nil
   895  }
   896  
   897  // ListDynamicLibrariesIn holds the arguments of ListDynamicLibraries
   898  type ListDynamicLibrariesIn struct {
   899  }
   900  
   901  // ListDynamicLibrariesOut holds the return values of ListDynamicLibraries
   902  type ListDynamicLibrariesOut struct {
   903  	List []api.Image
   904  }
   905  
   906  func (s *RPCServer) ListDynamicLibraries(in ListDynamicLibrariesIn, out *ListDynamicLibrariesOut) error {
   907  	imgs := s.debugger.ListDynamicLibraries()
   908  	out.List = make([]api.Image, 0, len(imgs))
   909  	for i := range imgs {
   910  		out.List = append(out.List, api.ConvertImage(imgs[i]))
   911  	}
   912  	return nil
   913  }
   914  
   915  // ListPackagesBuildInfoIn holds the arguments of ListPackages.
   916  type ListPackagesBuildInfoIn struct {
   917  	IncludeFiles bool
   918  }
   919  
   920  // ListPackagesBuildInfoOut holds the return values of ListPackages.
   921  type ListPackagesBuildInfoOut struct {
   922  	List []api.PackageBuildInfo
   923  }
   924  
   925  // ListPackagesBuildInfo returns the list of packages used by the program along with
   926  // the directory where each package was compiled and optionally the list of
   927  // files constituting the package.
   928  // Note that the directory path is a best guess and may be wrong is a tool
   929  // other than cmd/go is used to perform the build.
   930  func (s *RPCServer) ListPackagesBuildInfo(in ListPackagesBuildInfoIn, out *ListPackagesBuildInfoOut) error {
   931  	pkgs := s.debugger.ListPackagesBuildInfo(in.IncludeFiles)
   932  	out.List = make([]api.PackageBuildInfo, 0, len(pkgs))
   933  	for _, pkg := range pkgs {
   934  		var files []string
   935  
   936  		if len(pkg.Files) > 0 {
   937  			files = make([]string, 0, len(pkg.Files))
   938  			for file := range pkg.Files {
   939  				files = append(files, file)
   940  			}
   941  		}
   942  
   943  		sort.Strings(files)
   944  
   945  		out.List = append(out.List, api.PackageBuildInfo{
   946  			ImportPath:    pkg.ImportPath,
   947  			DirectoryPath: pkg.DirectoryPath,
   948  			Files:         files,
   949  		})
   950  	}
   951  	return nil
   952  }
   953  
   954  // ExamineMemoryIn holds the arguments of ExamineMemory
   955  type ExamineMemoryIn struct {
   956  	Address uint64
   957  	Length  int
   958  }
   959  
   960  // ExaminedMemoryOut holds the return values of ExamineMemory
   961  type ExaminedMemoryOut struct {
   962  	Mem            []byte
   963  	IsLittleEndian bool
   964  }
   965  
   966  func (s *RPCServer) ExamineMemory(arg ExamineMemoryIn, out *ExaminedMemoryOut) error {
   967  	if arg.Length > 1000 {
   968  		return fmt.Errorf("len must be less than or equal to 1000")
   969  	}
   970  	Mem, err := s.debugger.ExamineMemory(arg.Address, arg.Length)
   971  	if err != nil {
   972  		return err
   973  	}
   974  
   975  	out.Mem = Mem
   976  	out.IsLittleEndian = true //TODO: get byte order from debugger.target.BinInfo().Arch
   977  
   978  	return nil
   979  }
   980  
   981  type StopRecordingIn struct {
   982  }
   983  
   984  type StopRecordingOut struct {
   985  }
   986  
   987  func (s *RPCServer) StopRecording(arg StopRecordingIn, cb service.RPCCallback) {
   988  	close(cb.SetupDoneChan())
   989  	var out StopRecordingOut
   990  	err := s.debugger.StopRecording()
   991  	if err != nil {
   992  		cb.Return(nil, err)
   993  		return
   994  	}
   995  	cb.Return(out, nil)
   996  }
   997  
   998  type DumpStartIn struct {
   999  	Destination string
  1000  }
  1001  
  1002  type DumpStartOut struct {
  1003  	State api.DumpState
  1004  }
  1005  
  1006  // DumpStart starts a core dump to arg.Destination.
  1007  func (s *RPCServer) DumpStart(arg DumpStartIn, out *DumpStartOut) error {
  1008  	err := s.debugger.DumpStart(arg.Destination)
  1009  	if err != nil {
  1010  		return err
  1011  	}
  1012  	out.State = *api.ConvertDumpState(s.debugger.DumpWait(0))
  1013  	return nil
  1014  }
  1015  
  1016  type DumpWaitIn struct {
  1017  	Wait int
  1018  }
  1019  
  1020  type DumpWaitOut struct {
  1021  	State api.DumpState
  1022  }
  1023  
  1024  // DumpWait waits for the core dump to finish or for arg.Wait milliseconds.
  1025  // Wait == 0 means return immediately.
  1026  // Returns the core dump status
  1027  func (s *RPCServer) DumpWait(arg DumpWaitIn, out *DumpWaitOut) error {
  1028  	out.State = *api.ConvertDumpState(s.debugger.DumpWait(time.Duration(arg.Wait) * time.Millisecond))
  1029  	return nil
  1030  }
  1031  
  1032  type DumpCancelIn struct {
  1033  }
  1034  
  1035  type DumpCancelOut struct {
  1036  }
  1037  
  1038  // DumpCancel cancels the core dump.
  1039  func (s *RPCServer) DumpCancel(arg DumpCancelIn, out *DumpCancelOut) error {
  1040  	return s.debugger.DumpCancel()
  1041  }
  1042  
  1043  type CreateWatchpointIn struct {
  1044  	Scope api.EvalScope
  1045  	Expr  string
  1046  	Type  api.WatchType
  1047  }
  1048  
  1049  type CreateWatchpointOut struct {
  1050  	*api.Breakpoint
  1051  }
  1052  
  1053  func (s *RPCServer) CreateWatchpoint(arg CreateWatchpointIn, out *CreateWatchpointOut) error {
  1054  	var err error
  1055  	out.Breakpoint, err = s.debugger.CreateWatchpoint(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.Expr, arg.Type)
  1056  	return err
  1057  }
  1058  
  1059  type BuildIDIn struct {
  1060  }
  1061  
  1062  type BuildIDOut struct {
  1063  	BuildID string
  1064  }
  1065  
  1066  func (s *RPCServer) BuildID(arg BuildIDIn, out *BuildIDOut) error {
  1067  	out.BuildID = s.debugger.BuildID()
  1068  	return nil
  1069  }
  1070  
  1071  type ListTargetsIn struct {
  1072  }
  1073  
  1074  type ListTargetsOut struct {
  1075  	Targets []api.Target
  1076  }
  1077  
  1078  // ListTargets returns the list of targets we are currently attached to.
  1079  func (s *RPCServer) ListTargets(arg ListTargetsIn, out *ListTargetsOut) error {
  1080  	s.debugger.LockTarget()
  1081  	defer s.debugger.UnlockTarget()
  1082  	out.Targets = []api.Target{}
  1083  	for _, tgt := range s.debugger.TargetGroup().Targets() {
  1084  		if _, err := tgt.Valid(); err == nil {
  1085  			out.Targets = append(out.Targets, *api.ConvertTarget(tgt, s.debugger.ConvertThreadBreakpoint))
  1086  		}
  1087  	}
  1088  	return nil
  1089  }
  1090  
  1091  type FollowExecIn struct {
  1092  	Enable bool
  1093  	Regex  string
  1094  }
  1095  
  1096  type FollowExecOut struct {
  1097  }
  1098  
  1099  // FollowExec enables or disables follow exec mode.
  1100  func (s *RPCServer) FollowExec(arg FollowExecIn, out *FollowExecOut) error {
  1101  	return s.debugger.FollowExec(arg.Enable, arg.Regex)
  1102  }
  1103  
  1104  type FollowExecEnabledIn struct {
  1105  }
  1106  
  1107  type FollowExecEnabledOut struct {
  1108  	Enabled bool
  1109  }
  1110  
  1111  // FollowExecEnabled returns true if follow exec mode is enabled.
  1112  func (s *RPCServer) FollowExecEnabled(arg FollowExecEnabledIn, out *FollowExecEnabledOut) error {
  1113  	out.Enabled = s.debugger.FollowExecEnabled()
  1114  	return nil
  1115  }
  1116  
  1117  type DebugInfoDirectoriesIn struct {
  1118  	Set  bool
  1119  	List []string
  1120  }
  1121  
  1122  type DebugInfoDirectoriesOut struct {
  1123  	List []string
  1124  }
  1125  
  1126  func (s *RPCServer) DebugInfoDirectories(arg DebugInfoDirectoriesIn, out *DebugInfoDirectoriesOut) error {
  1127  	if arg.Set {
  1128  		s.debugger.SetDebugInfoDirectories(arg.List)
  1129  	}
  1130  	out.List = s.debugger.DebugInfoDirectories()
  1131  	return nil
  1132  }