gitlab.com/Raven-IO/raven-delve@v1.22.4/service/dap/server.go (about)

     1  // Package dap implements VSCode's Debug Adaptor Protocol (DAP).
     2  // This allows delve to communicate with frontends using DAP
     3  // without a separate adaptor. The frontend will run the debugger
     4  // (which now doubles as an adaptor) in server mode listening on
     5  // a port and communicating over TCP. This is work in progress,
     6  // so for now Delve in dap mode only supports synchronous
     7  // request-response communication, blocking while processing each request.
     8  // For DAP details see https://microsoft.github.io/debug-adapter-protocol.
     9  package dap
    10  
    11  import (
    12  	"bufio"
    13  	"bytes"
    14  	"encoding/json"
    15  	"errors"
    16  	"fmt"
    17  	"go/constant"
    18  	"go/parser"
    19  	"io"
    20  	"math"
    21  	"net"
    22  	"os"
    23  	"os/exec"
    24  	"path/filepath"
    25  	"reflect"
    26  	"regexp"
    27  	"runtime"
    28  	"runtime/debug"
    29  	"sort"
    30  	"strconv"
    31  	"strings"
    32  	"sync"
    33  	"time"
    34  
    35  	"gitlab.com/Raven-IO/raven-delve/pkg/gobuild"
    36  	"gitlab.com/Raven-IO/raven-delve/pkg/goversion"
    37  	"gitlab.com/Raven-IO/raven-delve/pkg/locspec"
    38  	"gitlab.com/Raven-IO/raven-delve/pkg/logflags"
    39  	"gitlab.com/Raven-IO/raven-delve/pkg/proc"
    40  
    41  	"github.com/google/go-dap"
    42  	"gitlab.com/Raven-IO/raven-delve/service"
    43  	"gitlab.com/Raven-IO/raven-delve/service/api"
    44  	"gitlab.com/Raven-IO/raven-delve/service/debugger"
    45  	"gitlab.com/Raven-IO/raven-delve/service/internal/sameuser"
    46  )
    47  
    48  // Server implements a DAP server that can accept a single client for
    49  // a single debug session (for now). It does not yet support restarting.
    50  // That means that in addition to explicit shutdown requests,
    51  // program termination and failed or closed client connection
    52  // would also result in stopping this single-use server.
    53  //
    54  // The DAP server operates via the following goroutines:
    55  //
    56  // (1) Main goroutine where the server is created via NewServer(),
    57  // started via Run() and stopped via Stop(). Once the server is
    58  // started, this goroutine blocks until it receives a stop-server
    59  // signal that can come from an OS interrupt (such as Ctrl-C) or
    60  // config.DisconnectChan (passed to NewServer()) as a result of
    61  // client connection failure or closure or a DAP disconnect request.
    62  //
    63  // (2) Run goroutine started from Run() that serves as both
    64  // a listener and a client goroutine. It accepts a client connection,
    65  // reads, decodes and dispatches each request from the client.
    66  // For synchronous requests, it issues commands to the
    67  // underlying debugger and sends back events and responses.
    68  // These requests block while the debuggee is running, so,
    69  // where applicable, the handlers need to check if debugging
    70  // state is running, so there is a need for a halt request or
    71  // a dummy/error response to avoid blocking.
    72  //
    73  // This is the only goroutine that sends a stop-server signal
    74  // via config.DisconnectChan when encountering a client connection
    75  // error or responding to a (synchronous) DAP disconnect request.
    76  // Once stop is triggered, the goroutine exits.
    77  //
    78  // Unlike rpccommon, there is not another layer of per-client
    79  // goroutines here because the dap server does not support
    80  // multiple clients.
    81  //
    82  // (3) Per-request goroutine is started for each asynchronous request
    83  // that resumes execution. We check if target is running already, so
    84  // there should be no more than one pending asynchronous request at
    85  // a time. This goroutine issues commands to the underlying debugger
    86  // and sends back events and responses. It takes a setup-done channel
    87  // as an argument and temporarily blocks the request loop until setup
    88  // for asynchronous execution is complete and target is running.
    89  // Once done, it unblocks processing of parallel requests unblocks
    90  // (e.g. disconnecting while the program is running).
    91  //
    92  // These per-request goroutines never send a stop-server signal.
    93  // They block on running debugger commands that are interrupted
    94  // when halt is issued while stopping. At that point these goroutines
    95  // wrap-up and exit.
    96  type Server struct {
    97  	// config is all the information necessary to start the debugger and server.
    98  	config *Config
    99  	// listener is used to accept the client connection.
   100  	// When working with a predetermined client, this is nil.
   101  	listener net.Listener
   102  	// session is the debug session that comes with a client connection.
   103  	session   *Session
   104  	sessionMu sync.Mutex
   105  }
   106  
   107  // Session is an abstraction for serving and shutting down
   108  // a DAP debug session with a pre-connected client.
   109  // TODO(polina): move this to a different file/package
   110  type Session struct {
   111  	config *Config
   112  
   113  	id int
   114  
   115  	// stackFrameHandles maps frames of each goroutine to unique ids across all goroutines.
   116  	// Reset at every stop.
   117  	stackFrameHandles *handlesMap
   118  	// variableHandles maps compound variables to unique references within their stack frame.
   119  	// Reset at every stop.
   120  	// See also comment for convertVariable.
   121  	variableHandles *variablesHandlesMap
   122  	// args tracks special settings for handling debug session requests.
   123  	args launchAttachArgs
   124  	// exceptionErr tracks the runtime error that last occurred.
   125  	exceptionErr error
   126  	// clientCapabilities tracks special settings for handling debug session requests.
   127  	clientCapabilities dapClientCapabilities
   128  
   129  	// mu synchronizes access to objects set on start-up (from run goroutine)
   130  	// and stopped on teardown (from main goroutine)
   131  	mu sync.Mutex
   132  
   133  	// conn is the accepted client connection.
   134  	conn *connection
   135  	// debugger is the underlying debugger service.
   136  	debugger *debugger.Debugger
   137  	// binaryToRemove is the temp compiled binary to be removed on disconnect (if any).
   138  	binaryToRemove string
   139  	// noDebugProcess is set for the noDebug launch process.
   140  	noDebugProcess *process
   141  
   142  	// sendingMu synchronizes writing to conn
   143  	// to ensure that messages do not get interleaved
   144  	sendingMu sync.Mutex
   145  
   146  	// runningCmd tracks whether the server is running an asynchronous
   147  	// command that resumes execution, which may not correspond to the actual
   148  	// running state of the process (e.g. if a command is temporarily interrupted).
   149  	runningCmd bool
   150  	runningMu  sync.Mutex
   151  
   152  	// haltRequested tracks whether a halt of the program has been requested, which may
   153  	// not correspond to whether a Halt Request has been sent to the target.
   154  	haltRequested bool
   155  	haltMu        sync.Mutex
   156  
   157  	// changeStateMu must be held for a request to protect itself from another goroutine
   158  	// changing the state of the running process at the same time.
   159  	changeStateMu sync.Mutex
   160  
   161  	// stdoutReader the program's stdout.
   162  	stdoutReader io.ReadCloser
   163  
   164  	// stderrReader the program's stderr.
   165  	stderrReader io.ReadCloser
   166  
   167  	// preTerminatedWG the WaitGroup that needs to wait before sending a terminated event.
   168  	preTerminatedWG sync.WaitGroup
   169  }
   170  
   171  // Config is all the information needed to start the debugger, handle
   172  // DAP connection traffic and signal to the server when it is time to stop.
   173  type Config struct {
   174  	*service.Config
   175  
   176  	// log is used for structured logging.
   177  	log logflags.Logger
   178  	// StopTriggered is closed when the server is Stop()-ed.
   179  	// Can be used to safeguard against duplicate shutdown sequences.
   180  	StopTriggered chan struct{}
   181  }
   182  
   183  type connection struct {
   184  	mu     sync.Mutex
   185  	closed bool
   186  	io.ReadWriteCloser
   187  }
   188  
   189  func (c *connection) Close() error {
   190  	c.mu.Lock()
   191  	defer c.mu.Unlock()
   192  	c.closed = true
   193  	return c.ReadWriteCloser.Close()
   194  }
   195  
   196  func (c *connection) isClosed() bool {
   197  	c.mu.Lock()
   198  	defer c.mu.Unlock()
   199  	return c.closed
   200  }
   201  
   202  type process struct {
   203  	*exec.Cmd
   204  	exited chan struct{}
   205  }
   206  
   207  // launchAttachArgs captures arguments from launch/attach request that
   208  // impact handling of subsequent requests.
   209  // The fields with cfgName tag can be updated through an evaluation request.
   210  type launchAttachArgs struct {
   211  	// stopOnEntry is set to automatically stop the debuggee after start.
   212  	stopOnEntry bool
   213  	// StackTraceDepth is the maximum length of the returned list of stack frames.
   214  	StackTraceDepth int `cfgName:"stackTraceDepth"`
   215  	// ShowGlobalVariables indicates if global package variables should be loaded.
   216  	ShowGlobalVariables bool `cfgName:"showGlobalVariables"`
   217  	// ShowRegisters indicates if register values should be loaded.
   218  	ShowRegisters bool `cfgName:"showRegisters"`
   219  	// GoroutineFilters are the filters used when loading goroutines.
   220  	GoroutineFilters string `cfgName:"goroutineFilters"`
   221  	// ShowPprofLabels is an array of keys of pprof labels to show as a
   222  	// goroutine name in the threads view. If the array has one element, only
   223  	// that label's value will be shown; otherwise, each of the labels will be
   224  	// shown as "key:value". To show all labels, specify the single element "*".
   225  	ShowPprofLabels []string `cfgName:"showPprofLabels"`
   226  	// HideSystemGoroutines indicates if system goroutines should be removed from threads
   227  	// responses.
   228  	HideSystemGoroutines bool `cfgName:"hideSystemGoroutines"`
   229  	// substitutePathClientToServer indicates rules for converting file paths between client and debugger.
   230  	substitutePathClientToServer [][2]string `cfgName:"substitutePath"`
   231  	// substitutePathServerToClient indicates rules for converting file paths between debugger and client.
   232  	substitutePathServerToClient [][2]string
   233  }
   234  
   235  // defaultArgs borrows the defaults for the arguments from the original vscode-go adapter.
   236  // TODO(polinasok): clean up this and its reference (Server.args)
   237  // in favor of default*Config variables defined in types.go.
   238  var defaultArgs = launchAttachArgs{
   239  	stopOnEntry:                  false,
   240  	StackTraceDepth:              50,
   241  	ShowGlobalVariables:          false,
   242  	HideSystemGoroutines:         false,
   243  	ShowRegisters:                false,
   244  	GoroutineFilters:             "",
   245  	ShowPprofLabels:              []string{},
   246  	substitutePathClientToServer: [][2]string{},
   247  	substitutePathServerToClient: [][2]string{},
   248  }
   249  
   250  // dapClientCapabilities captures arguments from initialize request that
   251  // impact handling of subsequent requests.
   252  type dapClientCapabilities struct {
   253  	supportsVariableType         bool
   254  	supportsVariablePaging       bool
   255  	supportsRunInTerminalRequest bool
   256  	supportsMemoryReferences     bool
   257  	supportsProgressReporting    bool
   258  }
   259  
   260  // DefaultLoadConfig controls how variables are loaded from the target's memory.
   261  // These limits are conservative to minimize performance overhead for bulk loading.
   262  // With dlv-dap, users do not have a way to adjust these.
   263  // Instead, we are focusing in interactive loading with nested reloads, array/map
   264  // paging and context-specific string limits.
   265  var DefaultLoadConfig = proc.LoadConfig{
   266  	FollowPointers:     true,
   267  	MaxVariableRecurse: 1,
   268  	// TODO(polina): consider 1024 limit instead:
   269  	// - vscode+C appears to use 1024 as the load limit
   270  	// - vscode viewlet hover truncates at 1023 characters
   271  	MaxStringLen:    512,
   272  	MaxArrayValues:  64,
   273  	MaxStructFields: -1,
   274  }
   275  
   276  const (
   277  	// When a user examines a single string, we can relax the loading limit.
   278  	maxSingleStringLen = 4 << 10 // 4096
   279  	// Results of a call are single-use and transient. We need to maximize
   280  	// what is presented. A common use case of a call injection is to
   281  	// stringify complex data conveniently.
   282  	maxStringLenInCallRetVars = 1 << 10 // 1024
   283  )
   284  
   285  // Max number of goroutines that we will return.
   286  // This is a var for testing
   287  var maxGoroutines = 1 << 10
   288  
   289  // NewServer creates a new DAP Server. It takes an opened Listener
   290  // via config and assumes its ownership. config.DisconnectChan has to be set;
   291  // it will be closed by the server when the client fails to connect,
   292  // disconnects or requests shutdown. Once config.DisconnectChan is closed,
   293  // Server.Stop() must be called to shutdown this single-user server.
   294  //
   295  // NewServer can be used to create a special DAP Server that works
   296  // only with a predetermined client. In that case, config.Listener is
   297  // nil and its RunWithClient must be used instead of Run.
   298  func NewServer(config *service.Config) *Server {
   299  	logger := logflags.DAPLogger()
   300  	if config.Listener != nil {
   301  		logflags.WriteDAPListeningMessage(config.Listener.Addr())
   302  	} else {
   303  		logger.Debug("DAP server for a predetermined client")
   304  	}
   305  	logger.Debug("DAP server pid = ", os.Getpid())
   306  	if config.AcceptMulti {
   307  		logger.Warn("DAP server does not support accept-multiclient mode")
   308  		config.AcceptMulti = false
   309  	}
   310  	return &Server{
   311  		config: &Config{
   312  			Config:        config,
   313  			log:           logger,
   314  			StopTriggered: make(chan struct{}),
   315  		},
   316  		listener: config.Listener,
   317  	}
   318  }
   319  
   320  var sessionCount = 0
   321  
   322  // NewSession creates a new client session that can handle DAP traffic.
   323  // It takes an open connection and provides a Close() method to shut it
   324  // down when the DAP session disconnects or a connection error occurs.
   325  func NewSession(conn io.ReadWriteCloser, config *Config, debugger *debugger.Debugger) *Session {
   326  	sessionCount++
   327  	if config.log == nil {
   328  		config.log = logflags.DAPLogger()
   329  	}
   330  	config.log.Debugf("DAP connection %d started", sessionCount)
   331  	if config.StopTriggered == nil {
   332  		config.log.Error("Session must be configured with StopTriggered")
   333  		os.Exit(1)
   334  	}
   335  	return &Session{
   336  		config:            config,
   337  		id:                sessionCount,
   338  		conn:              &connection{ReadWriteCloser: conn},
   339  		stackFrameHandles: newHandlesMap(),
   340  		variableHandles:   newVariablesHandlesMap(),
   341  		args:              defaultArgs,
   342  		exceptionErr:      nil,
   343  		debugger:          debugger,
   344  	}
   345  }
   346  
   347  // If user-specified options are provided via Launch/AttachRequest,
   348  // we override the defaults for optional args.
   349  func (s *Session) setLaunchAttachArgs(args LaunchAttachCommonConfig) {
   350  	s.args.stopOnEntry = args.StopOnEntry
   351  	if depth := args.StackTraceDepth; depth > 0 {
   352  		s.args.StackTraceDepth = depth
   353  	}
   354  	s.args.ShowGlobalVariables = args.ShowGlobalVariables
   355  	s.args.ShowRegisters = args.ShowRegisters
   356  	s.args.HideSystemGoroutines = args.HideSystemGoroutines
   357  	s.args.GoroutineFilters = args.GoroutineFilters
   358  	s.args.ShowPprofLabels = args.ShowPprofLabels
   359  	if paths := args.SubstitutePath; len(paths) > 0 {
   360  		clientToServer := make([][2]string, 0, len(paths))
   361  		serverToClient := make([][2]string, 0, len(paths))
   362  		for _, p := range paths {
   363  			clientToServer = append(clientToServer, [2]string{p.From, p.To})
   364  			serverToClient = append(serverToClient, [2]string{p.To, p.From})
   365  		}
   366  		s.args.substitutePathClientToServer = clientToServer
   367  		s.args.substitutePathServerToClient = serverToClient
   368  	}
   369  }
   370  
   371  // Stop stops the DAP debugger service, closes the listener and the client
   372  // connection. It shuts down the underlying debugger and kills the target
   373  // process if it was launched by it or stops the noDebug process.
   374  // This method mustn't be called more than once.
   375  // StopTriggered notifies other goroutines that stop is in progress.
   376  func (s *Server) Stop() {
   377  	s.config.log.Debug("DAP server stopping...")
   378  	defer s.config.log.Debug("DAP server stopped")
   379  	close(s.config.StopTriggered)
   380  
   381  	if s.listener != nil {
   382  		// If run goroutine is blocked on accept, this will unblock it.
   383  		s.listener.Close()
   384  	}
   385  
   386  	s.sessionMu.Lock()
   387  	defer s.sessionMu.Unlock()
   388  	if s.session == nil {
   389  		return
   390  	}
   391  	// If run goroutine is blocked on read, this will unblock it.
   392  	s.session.Close()
   393  }
   394  
   395  // Close closes the underlying debugger/process and connection.
   396  // May be called more than once.
   397  func (s *Session) Close() {
   398  	s.mu.Lock()
   399  	defer s.mu.Unlock()
   400  
   401  	if s.debugger != nil {
   402  		killProcess := s.debugger.AttachPid() == 0
   403  		s.stopDebugSession(killProcess)
   404  	} else if s.noDebugProcess != nil {
   405  		s.stopNoDebugProcess()
   406  	}
   407  	// The binary is no longer in use by the debugger. It is safe to remove it.
   408  	if s.binaryToRemove != "" {
   409  		gobuild.Remove(s.binaryToRemove)
   410  		s.binaryToRemove = "" // avoid error printed on duplicate removal
   411  	}
   412  	// Close client connection last, so other shutdown stages
   413  	// can send client notifications.
   414  	// Unless Stop() was called after read loop in ServeDAPCodec()
   415  	// returned, this will result in a closed connection error
   416  	// on next read, breaking out the read loop and
   417  	// allowing the run goroutines to exit.
   418  	// This connection is closed here and in serveDAPCodec().
   419  	// If this was a forced shutdown, external stop logic can close this first.
   420  	// If this was a client loop exit (on error or disconnect), serveDAPCodec()
   421  	// will be first.
   422  	// Duplicate close calls return an error, but are not fatal.
   423  	s.conn.Close()
   424  }
   425  
   426  // triggerServerStop closes DisconnectChan if not nil, which
   427  // signals that client sent a disconnect request or there was connection
   428  // failure or closure. Since the server currently services only one
   429  // client, this is used as a signal to stop the entire server.
   430  // The function safeguards against closing the channel more
   431  // than once and can be called multiple times. It is not thread-safe
   432  // and is currently only called from the run goroutine.
   433  func (c *Config) triggerServerStop() {
   434  	// Avoid accidentally closing the channel twice and causing a panic, when
   435  	// this function is called more than once because stop was triggered
   436  	// by multiple conditions simultaneously.
   437  	if c.DisconnectChan != nil {
   438  		close(c.DisconnectChan)
   439  		c.DisconnectChan = nil
   440  	}
   441  	// There should be no logic here after the stop-server
   442  	// signal that might cause everything to shut down before this
   443  	// logic gets executed.
   444  }
   445  
   446  // Run launches a new goroutine where it accepts a client connection
   447  // and starts processing requests from it. Use Stop() to close connection.
   448  // The server does not support multiple clients, serially or in parallel.
   449  // The server should be restarted for every new debug session.
   450  // The debugger won't be started until launch/attach request is received.
   451  // TODO(polina): allow new client connections for new debug sessions,
   452  // so the editor needs to launch dap server only once? Note that some requests
   453  // may change the server's environment (e.g. see dlvCwd of launch configuration).
   454  // So if we want to reuse this server for multiple independent debugging sessions
   455  // we need to take that into consideration.
   456  func (s *Server) Run() {
   457  	if s.listener == nil {
   458  		s.config.log.Error("Misconfigured server: no Listener is configured.")
   459  		os.Exit(1)
   460  	}
   461  
   462  	go func() {
   463  		conn, err := s.listener.Accept() // listener is closed in Stop()
   464  		if err != nil {
   465  			select {
   466  			case <-s.config.StopTriggered:
   467  			default:
   468  				s.config.log.Errorf("Error accepting client connection: %s\n", err)
   469  				s.config.triggerServerStop()
   470  			}
   471  			return
   472  		}
   473  		if s.config.CheckLocalConnUser {
   474  			if !sameuser.CanAccept(s.listener.Addr(), conn.LocalAddr(), conn.RemoteAddr()) {
   475  				s.config.log.Error("Error accepting client connection: Only connections from the same user that started this instance of Delve are allowed to connect. See --only-same-user.")
   476  				s.config.triggerServerStop()
   477  				return
   478  			}
   479  		}
   480  		s.runSession(conn)
   481  	}()
   482  }
   483  
   484  func (s *Server) runSession(conn io.ReadWriteCloser) {
   485  	s.sessionMu.Lock()
   486  	s.session = NewSession(conn, s.config, nil) // closed in Stop()
   487  	s.sessionMu.Unlock()
   488  	s.session.ServeDAPCodec()
   489  }
   490  
   491  // RunWithClient is similar to Run but works only with an already established
   492  // connection instead of waiting on the listener to accept a new client.
   493  // RunWithClient takes ownership of conn. Debugger won't be started
   494  // until a launch/attach request is received over the connection.
   495  func (s *Server) RunWithClient(conn net.Conn) {
   496  	if s.listener != nil {
   497  		s.config.log.Error("RunWithClient must not be used when the Server is configured with a Listener")
   498  		os.Exit(1)
   499  	}
   500  	s.config.log.Debugf("Connected to the client at %s", conn.RemoteAddr())
   501  	go s.runSession(conn)
   502  }
   503  
   504  func (s *Session) address() string {
   505  	if s.config.Listener != nil {
   506  		return s.config.Listener.Addr().String()
   507  	}
   508  	if netconn, ok := s.conn.ReadWriteCloser.(net.Conn); ok {
   509  		return netconn.LocalAddr().String()
   510  	}
   511  	return ""
   512  }
   513  
   514  // ServeDAPCodec reads and decodes requests from the client
   515  // until it encounters an error or EOF, when it sends
   516  // a disconnect signal and returns.
   517  func (s *Session) ServeDAPCodec() {
   518  	// Close conn, but not the debugger in case we are in AcceptMulti mode.
   519  	// If not, debugger will be shut down in Stop().
   520  	var triggerServerStop bool
   521  	defer s.conn.Close()
   522  	defer func() {
   523  		if triggerServerStop {
   524  			s.config.triggerServerStop()
   525  		}
   526  	}()
   527  	reader := bufio.NewReader(s.conn)
   528  	for {
   529  		request, err := dap.ReadProtocolMessage(reader)
   530  		// Handle dap.DecodeProtocolMessageFieldError errors gracefully by responding with an ErrorResponse.
   531  		// For example:
   532  		// -- "Request command 'foo' is not supported" means we
   533  		// potentially got some new DAP request that we do not yet have
   534  		// decoding support for, so we can respond with an ErrorResponse.
   535  		//
   536  		// Other errors, such as unmarshalling errors, will log the error and cause the server to trigger
   537  		// a stop.
   538  		if err != nil {
   539  			s.config.log.Debug("DAP error: ", err)
   540  			select {
   541  			case <-s.config.StopTriggered:
   542  			default:
   543  				triggerServerStop = !s.config.AcceptMulti
   544  				if err != io.EOF { // EOF means client closed connection
   545  					var decodeErr *dap.DecodeProtocolMessageFieldError
   546  					if errors.As(err, &decodeErr) {
   547  						// Send an error response to the users if we were unable to process the message.
   548  						s.sendInternalErrorResponse(decodeErr.Seq, err.Error())
   549  						continue
   550  					}
   551  					s.config.log.Error("DAP error: ", err)
   552  				}
   553  			}
   554  			return
   555  		}
   556  		s.handleRequest(request)
   557  
   558  		if _, ok := request.(*dap.DisconnectRequest); ok {
   559  			// disconnect already shut things down and triggered stopping
   560  			return
   561  		}
   562  	}
   563  }
   564  
   565  // In case a handler panics, we catch the panic to avoid crashing both
   566  // the server and the target. We send an error response back, but
   567  // in case it's a dup and ignored by the client, we also log the error.
   568  func (s *Session) recoverPanic(request dap.Message) {
   569  	if ierr := recover(); ierr != nil {
   570  		s.config.log.Errorf("recovered panic: %s\n%s\n", ierr, debug.Stack())
   571  		s.sendInternalErrorResponse(request.GetSeq(), fmt.Sprintf("%v", ierr))
   572  	}
   573  }
   574  
   575  func (s *Session) handleRequest(request dap.Message) {
   576  	defer s.recoverPanic(request)
   577  	jsonmsg, _ := json.Marshal(request)
   578  	s.config.log.Debug("[<- from client]", string(jsonmsg))
   579  
   580  	if _, ok := request.(dap.RequestMessage); !ok {
   581  		s.sendInternalErrorResponse(request.GetSeq(), fmt.Sprintf("Unable to process non-request %#v\n", request))
   582  		return
   583  	}
   584  
   585  	if s.isNoDebug() {
   586  		switch request := request.(type) {
   587  		case *dap.DisconnectRequest:
   588  			s.onDisconnectRequest(request)
   589  		case *dap.RestartRequest:
   590  			s.sendUnsupportedErrorResponse(request.Request)
   591  		default:
   592  			r := request.(dap.RequestMessage).GetRequest()
   593  			s.sendErrorResponse(*r, NoDebugIsRunning, "noDebug mode", fmt.Sprintf("unable to process '%s' request", r.Command))
   594  		}
   595  		return
   596  	}
   597  
   598  	// These requests, can be handled regardless of whether the target is running
   599  	switch request := request.(type) {
   600  	case *dap.InitializeRequest: // Required
   601  		s.onInitializeRequest(request)
   602  		return
   603  	case *dap.LaunchRequest: // Required
   604  		s.onLaunchRequest(request)
   605  		return
   606  	case *dap.AttachRequest: // Required
   607  		s.onAttachRequest(request)
   608  		return
   609  	case *dap.DisconnectRequest: // Required
   610  		s.onDisconnectRequest(request)
   611  		return
   612  	case *dap.PauseRequest: // Required
   613  		s.onPauseRequest(request)
   614  		return
   615  	case *dap.TerminateRequest: // Optional (capability 'supportsTerminateRequest')
   616  		/*TODO*/ s.onTerminateRequest(request) // not yet implemented
   617  		return
   618  	case *dap.RestartRequest: // Optional (capability 'supportsRestartRequest')
   619  		/*TODO*/ s.onRestartRequest(request) // not yet implemented
   620  		return
   621  	}
   622  
   623  	// Most requests cannot be processed while the debuggee is running.
   624  	// We have a couple of options for handling these without blocking
   625  	// the request loop indefinitely when we are in running state.
   626  	// --1-- Return a dummy response or an error right away.
   627  	// --2-- Halt execution, process the request, maybe resume execution.
   628  	// --3-- Handle such requests asynchronously and let them block until
   629  	// the process stops or terminates (e.g. using a channel and a single
   630  	// goroutine to preserve the order). This might not be appropriate
   631  	// for requests such as continue or step because they would skip
   632  	// the stop, resuming execution right away. Other requests
   633  	// might not be relevant anymore when the stop is finally reached, and
   634  	// state changed from the previous snapshot. The user might want to
   635  	// resume execution before the backlog of buffered requests is cleared,
   636  	// so we would have to either cancel them or delay processing until
   637  	// the next stop. In addition, the editor itself might block waiting
   638  	// for these requests to return. We are not aware of any requests
   639  	// that would benefit from this approach at this time.
   640  	if s.debugger != nil && s.debugger.IsRunning() || s.isRunningCmd() {
   641  		switch request := request.(type) {
   642  		case *dap.ThreadsRequest: // Required
   643  			// On start-up, the client requests the baseline of currently existing threads
   644  			// right away as there are a number of DAP requests that require a thread id
   645  			// (pause, continue, stacktrace, etc.). This can happen after the program
   646  			// continues on entry, preventing the client from handling any pause requests
   647  			// from the user. We remedy this by sending back a placeholder thread id
   648  			// for the current goroutine.
   649  			response := &dap.ThreadsResponse{
   650  				Response: *newResponse(request.Request),
   651  				Body:     dap.ThreadsResponseBody{Threads: []dap.Thread{{Id: -1, Name: "Current"}}},
   652  			}
   653  			s.send(response)
   654  		case *dap.SetBreakpointsRequest: // Required
   655  			s.changeStateMu.Lock()
   656  			defer s.changeStateMu.Unlock()
   657  			s.config.log.Debug("halting execution to set breakpoints")
   658  			_, err := s.halt()
   659  			if err != nil {
   660  				s.sendErrorResponse(request.Request, UnableToSetBreakpoints, "Unable to set or clear breakpoints", err.Error())
   661  				return
   662  			}
   663  			s.onSetBreakpointsRequest(request)
   664  		case *dap.SetFunctionBreakpointsRequest: // Optional (capability 'supportsFunctionBreakpoints')
   665  			s.changeStateMu.Lock()
   666  			defer s.changeStateMu.Unlock()
   667  			s.config.log.Debug("halting execution to set breakpoints")
   668  			_, err := s.halt()
   669  			if err != nil {
   670  				s.sendErrorResponse(request.Request, UnableToSetBreakpoints, "Unable to set or clear breakpoints", err.Error())
   671  				return
   672  			}
   673  			s.onSetFunctionBreakpointsRequest(request)
   674  		default:
   675  			r := request.(dap.RequestMessage).GetRequest()
   676  			s.sendErrorResponse(*r, DebuggeeIsRunning, fmt.Sprintf("Unable to process `%s`", r.Command), "debuggee is running")
   677  		}
   678  		return
   679  	}
   680  
   681  	// Requests below can only be handled while target is stopped.
   682  	// Some of them are blocking and will be handled synchronously
   683  	// on this goroutine while non-blocking requests will be dispatched
   684  	// to another goroutine. Please note that because of the running
   685  	// check above, there should be no more than one pending asynchronous
   686  	// request at a time.
   687  
   688  	// Non-blocking request handlers will signal when they are ready
   689  	// setting up for async execution, so more requests can be processed.
   690  	resumeRequestLoop := newSyncflag()
   691  
   692  	switch request := request.(type) {
   693  	//--- Asynchronous requests ---
   694  	case *dap.ConfigurationDoneRequest: // Optional (capability 'supportsConfigurationDoneRequest')
   695  		go func() {
   696  			defer s.recoverPanic(request)
   697  			s.onConfigurationDoneRequest(request, resumeRequestLoop)
   698  		}()
   699  		resumeRequestLoop.wait()
   700  	case *dap.ContinueRequest: // Required
   701  		go func() {
   702  			defer s.recoverPanic(request)
   703  			s.onContinueRequest(request, resumeRequestLoop)
   704  		}()
   705  		resumeRequestLoop.wait()
   706  	case *dap.NextRequest: // Required
   707  		go func() {
   708  			defer s.recoverPanic(request)
   709  			s.onNextRequest(request, resumeRequestLoop)
   710  		}()
   711  		resumeRequestLoop.wait()
   712  	case *dap.StepInRequest: // Required
   713  		go func() {
   714  			defer s.recoverPanic(request)
   715  			s.onStepInRequest(request, resumeRequestLoop)
   716  		}()
   717  		resumeRequestLoop.wait()
   718  	case *dap.StepOutRequest: // Required
   719  		go func() {
   720  			defer s.recoverPanic(request)
   721  			s.onStepOutRequest(request, resumeRequestLoop)
   722  		}()
   723  		resumeRequestLoop.wait()
   724  	case *dap.StepBackRequest: // Optional (capability 'supportsStepBack')
   725  		go func() {
   726  			defer s.recoverPanic(request)
   727  			s.onStepBackRequest(request, resumeRequestLoop)
   728  		}()
   729  		resumeRequestLoop.wait()
   730  	case *dap.ReverseContinueRequest: // Optional (capability 'supportsStepBack')
   731  		go func() {
   732  			defer s.recoverPanic(request)
   733  			s.onReverseContinueRequest(request, resumeRequestLoop)
   734  		}()
   735  		resumeRequestLoop.wait()
   736  	//--- Synchronous requests ---
   737  	case *dap.SetBreakpointsRequest: // Required
   738  		s.onSetBreakpointsRequest(request)
   739  	case *dap.SetFunctionBreakpointsRequest: // Optional (capability 'supportsFunctionBreakpoints')
   740  		s.onSetFunctionBreakpointsRequest(request)
   741  	case *dap.SetInstructionBreakpointsRequest: // Optional (capability 'supportsInstructionBreakpoints')
   742  		s.onSetInstructionBreakpointsRequest(request)
   743  	case *dap.SetExceptionBreakpointsRequest: // Optional (capability 'exceptionBreakpointFilters')
   744  		s.onSetExceptionBreakpointsRequest(request)
   745  	case *dap.ThreadsRequest: // Required
   746  		s.onThreadsRequest(request)
   747  	case *dap.StackTraceRequest: // Required
   748  		s.onStackTraceRequest(request)
   749  	case *dap.ScopesRequest: // Required
   750  		s.onScopesRequest(request)
   751  	case *dap.VariablesRequest: // Required
   752  		s.onVariablesRequest(request)
   753  	case *dap.EvaluateRequest: // Required
   754  		s.onEvaluateRequest(request)
   755  	case *dap.SetVariableRequest: // Optional (capability 'supportsSetVariable')
   756  		s.onSetVariableRequest(request)
   757  	case *dap.ExceptionInfoRequest: // Optional (capability 'supportsExceptionInfoRequest')
   758  		s.onExceptionInfoRequest(request)
   759  	case *dap.DisassembleRequest: // Optional (capability 'supportsDisassembleRequest')
   760  		s.onDisassembleRequest(request)
   761  	//--- Requests that we may want to support ---
   762  	case *dap.SourceRequest: // Required
   763  		/*TODO*/ s.sendUnsupportedErrorResponse(request.Request) // https://gitlab.com/Raven-IO/raven-delve/issues/2851
   764  	case *dap.SetExpressionRequest: // Optional (capability 'supportsSetExpression')
   765  		/*TODO*/ s.onSetExpressionRequest(request) // Not yet implemented
   766  	case *dap.LoadedSourcesRequest: // Optional (capability 'supportsLoadedSourcesRequest')
   767  		/*TODO*/ s.onLoadedSourcesRequest(request) // Not yet implemented
   768  	case *dap.ReadMemoryRequest: // Optional (capability 'supportsReadMemoryRequest')
   769  		/*TODO*/ s.onReadMemoryRequest(request) // Not yet implemented
   770  	case *dap.CancelRequest: // Optional (capability 'supportsCancelRequest')
   771  		/*TODO*/ s.onCancelRequest(request) // Not yet implemented (does this make sense?)
   772  	case *dap.ModulesRequest: // Optional (capability 'supportsModulesRequest')
   773  		/*TODO*/ s.sendUnsupportedErrorResponse(request.Request) // Not yet implemented (does this make sense?)
   774  	//--- Requests that we do not plan to support ---
   775  	case *dap.RestartFrameRequest: // Optional (capability 'supportsRestartFrame')
   776  		s.sendUnsupportedErrorResponse(request.Request)
   777  	case *dap.GotoRequest: // Optional (capability 'supportsGotoTargetsRequest')
   778  		s.sendUnsupportedErrorResponse(request.Request)
   779  	case *dap.TerminateThreadsRequest: // Optional (capability 'supportsTerminateThreadsRequest')
   780  		s.sendUnsupportedErrorResponse(request.Request)
   781  	case *dap.StepInTargetsRequest: // Optional (capability 'supportsStepInTargetsRequest')
   782  		s.sendUnsupportedErrorResponse(request.Request)
   783  	case *dap.GotoTargetsRequest: // Optional (capability 'supportsGotoTargetsRequest')
   784  		s.sendUnsupportedErrorResponse(request.Request)
   785  	case *dap.CompletionsRequest: // Optional (capability 'supportsCompletionsRequest')
   786  		s.sendUnsupportedErrorResponse(request.Request)
   787  	case *dap.DataBreakpointInfoRequest: // Optional (capability 'supportsDataBreakpoints')
   788  		s.sendUnsupportedErrorResponse(request.Request)
   789  	case *dap.SetDataBreakpointsRequest: // Optional (capability 'supportsDataBreakpoints')
   790  		s.sendUnsupportedErrorResponse(request.Request)
   791  	case *dap.BreakpointLocationsRequest: // Optional (capability 'supportsBreakpointLocationsRequest')
   792  		s.sendUnsupportedErrorResponse(request.Request)
   793  	default:
   794  		// This is a DAP message that go-dap has a struct for, so
   795  		// decoding succeeded, but this function does not know how
   796  		// to handle.
   797  		s.sendInternalErrorResponse(request.GetSeq(), fmt.Sprintf("Unable to process %#v\n", request))
   798  	}
   799  }
   800  
   801  func (s *Session) send(message dap.Message) {
   802  	jsonmsg, _ := json.Marshal(message)
   803  	s.config.log.Debug("[-> to client]", string(jsonmsg))
   804  	// TODO(polina): consider using a channel for all the sends and to have a dedicated
   805  	// goroutine that reads from that channel and sends over the connection.
   806  	// This will avoid blocking on slow network sends.
   807  	s.sendingMu.Lock()
   808  	defer s.sendingMu.Unlock()
   809  	err := dap.WriteProtocolMessage(s.conn, message)
   810  	if err != nil {
   811  		s.config.log.Debug(err)
   812  	}
   813  }
   814  
   815  func (s *Session) logToConsole(msg string) {
   816  	s.send(&dap.OutputEvent{
   817  		Event: *newEvent("output"),
   818  		Body: dap.OutputEventBody{
   819  			Output:   msg + "\n",
   820  			Category: "console",
   821  		},
   822  	})
   823  }
   824  
   825  func (s *Session) onInitializeRequest(request *dap.InitializeRequest) {
   826  	s.setClientCapabilities(request.Arguments)
   827  	if request.Arguments.PathFormat != "path" {
   828  		s.sendErrorResponse(request.Request, FailedToInitialize, "Failed to initialize",
   829  			fmt.Sprintf("Unsupported 'pathFormat' value '%s'.", request.Arguments.PathFormat))
   830  		return
   831  	}
   832  	if !request.Arguments.LinesStartAt1 {
   833  		s.sendErrorResponse(request.Request, FailedToInitialize, "Failed to initialize",
   834  			"Only 1-based line numbers are supported.")
   835  		return
   836  	}
   837  	if !request.Arguments.ColumnsStartAt1 {
   838  		s.sendErrorResponse(request.Request, FailedToInitialize, "Failed to initialize",
   839  			"Only 1-based column numbers are supported.")
   840  		return
   841  	}
   842  
   843  	// TODO(polina): Respond with an error if debug session started
   844  	// with an initialize request is in progress?
   845  	response := &dap.InitializeResponse{Response: *newResponse(request.Request)}
   846  	response.Body.SupportsConfigurationDoneRequest = true
   847  	response.Body.SupportsConditionalBreakpoints = true
   848  	response.Body.SupportsDelayedStackTraceLoading = true
   849  	response.Body.SupportsFunctionBreakpoints = true
   850  	response.Body.SupportsInstructionBreakpoints = true
   851  	response.Body.SupportsExceptionInfoRequest = true
   852  	response.Body.SupportsSetVariable = true
   853  	response.Body.SupportsEvaluateForHovers = true
   854  	response.Body.SupportsClipboardContext = true
   855  	response.Body.SupportsSteppingGranularity = true
   856  	response.Body.SupportsLogPoints = true
   857  	response.Body.SupportsDisassembleRequest = true
   858  	// To be enabled by CapabilitiesEvent based on launch configuration
   859  	response.Body.SupportsStepBack = false
   860  	response.Body.SupportTerminateDebuggee = false
   861  	// TODO(polina): support these requests in addition to vscode-go feature parity
   862  	response.Body.SupportsTerminateRequest = false
   863  	response.Body.SupportsRestartRequest = false
   864  	response.Body.SupportsSetExpression = false
   865  	response.Body.SupportsLoadedSourcesRequest = false
   866  	response.Body.SupportsReadMemoryRequest = false
   867  	response.Body.SupportsCancelRequest = false
   868  	s.send(response)
   869  }
   870  
   871  func (s *Session) setClientCapabilities(args dap.InitializeRequestArguments) {
   872  	s.clientCapabilities.supportsMemoryReferences = args.SupportsMemoryReferences
   873  	s.clientCapabilities.supportsProgressReporting = args.SupportsProgressReporting
   874  	s.clientCapabilities.supportsRunInTerminalRequest = args.SupportsRunInTerminalRequest
   875  	s.clientCapabilities.supportsVariablePaging = args.SupportsVariablePaging
   876  	s.clientCapabilities.supportsVariableType = args.SupportsVariableType
   877  }
   878  
   879  func cleanExeName(name string) string {
   880  	if runtime.GOOS == "windows" && filepath.Ext(name) != ".exe" {
   881  		return name + ".exe"
   882  	}
   883  	return name
   884  }
   885  
   886  func (s *Session) onLaunchRequest(request *dap.LaunchRequest) {
   887  	var err error
   888  	if s.debugger != nil {
   889  		s.sendShowUserErrorResponse(request.Request, FailedToLaunch, "Failed to launch",
   890  			fmt.Sprintf("debug session already in progress at %s - use remote attach mode to connect to a server with an active debug session", s.address()))
   891  		return
   892  	}
   893  
   894  	args := defaultLaunchConfig // narrow copy for initializing non-zero default values
   895  	if err := unmarshalLaunchAttachArgs(request.Arguments, &args); err != nil {
   896  		s.sendShowUserErrorResponse(request.Request,
   897  			FailedToLaunch, "Failed to launch", fmt.Sprintf("invalid debug configuration - %v", err))
   898  		return
   899  	}
   900  	s.config.log.Debug("parsed launch config: ", prettyPrint(args))
   901  
   902  	if args.DlvCwd != "" {
   903  		if err := os.Chdir(args.DlvCwd); err != nil {
   904  			s.sendShowUserErrorResponse(request.Request,
   905  				FailedToLaunch, "Failed to launch", fmt.Sprintf("failed to chdir to %q - %v", args.DlvCwd, err))
   906  			return
   907  		}
   908  	}
   909  
   910  	for k, v := range args.Env {
   911  		if v != nil {
   912  			if err := os.Setenv(k, *v); err != nil {
   913  				s.sendShowUserErrorResponse(request.Request, FailedToLaunch, "Failed to launch", fmt.Sprintf("failed to setenv(%v) - %v", k, err))
   914  				return
   915  			}
   916  		} else {
   917  			if err := os.Unsetenv(k); err != nil {
   918  				s.sendShowUserErrorResponse(request.Request, FailedToLaunch, "Failed to launch", fmt.Sprintf("failed to unsetenv(%v) - %v", k, err))
   919  				return
   920  			}
   921  		}
   922  	}
   923  
   924  	if args.Mode == "" {
   925  		args.Mode = "debug"
   926  	}
   927  	if !isValidLaunchMode(args.Mode) {
   928  		s.sendShowUserErrorResponse(request.Request, FailedToLaunch, "Failed to launch",
   929  			fmt.Sprintf("invalid debug configuration - unsupported 'mode' attribute %q", args.Mode))
   930  		return
   931  	}
   932  
   933  	if args.Program == "" && args.Mode != "replay" { // Only fail on modes requiring a program
   934  		s.sendShowUserErrorResponse(request.Request, FailedToLaunch, "Failed to launch",
   935  			"The program attribute is missing in debug configuration.")
   936  		return
   937  	}
   938  
   939  	if args.Backend == "" {
   940  		args.Backend = "default"
   941  	}
   942  
   943  	if args.Mode == "replay" {
   944  		// Validate trace directory
   945  		if args.TraceDirPath == "" {
   946  			s.sendShowUserErrorResponse(request.Request, FailedToLaunch, "Failed to launch",
   947  				"The 'traceDirPath' attribute is missing in debug configuration.")
   948  			return
   949  		}
   950  
   951  		// Assign the rr trace directory path to debugger configuration
   952  		s.config.Debugger.CoreFile = args.TraceDirPath
   953  		args.Backend = "rr"
   954  	}
   955  	if args.Mode == "core" {
   956  		// Validate core dump path
   957  		if args.CoreFilePath == "" {
   958  			s.sendShowUserErrorResponse(request.Request, FailedToLaunch, "Failed to launch",
   959  				"The 'coreFilePath' attribute is missing in debug configuration.")
   960  			return
   961  		}
   962  		// Assign the non-empty core file path to debugger configuration. This will
   963  		// trigger a native core file replay instead of a rr trace replay
   964  		s.config.Debugger.CoreFile = args.CoreFilePath
   965  		args.Backend = "core"
   966  	}
   967  
   968  	s.config.Debugger.Backend = args.Backend
   969  
   970  	// Prepare the debug executable filename, building it if necessary
   971  	debugbinary := args.Program
   972  	if args.Mode == "debug" || args.Mode == "test" {
   973  		deleteOnError := false
   974  		if args.Output == "" {
   975  			deleteOnError = true
   976  			args.Output = gobuild.DefaultDebugBinaryPath("__debug_bin")
   977  		} else {
   978  			args.Output = cleanExeName(args.Output)
   979  		}
   980  		args.Output, err = filepath.Abs(args.Output)
   981  		if err != nil {
   982  			s.sendShowUserErrorResponse(request.Request, FailedToLaunch, "Failed to launch", err.Error())
   983  			return
   984  		}
   985  		debugbinary = args.Output
   986  
   987  		var cmd string
   988  		var out []byte
   989  
   990  		switch args.Mode {
   991  		case "debug":
   992  			cmd, out, err = gobuild.GoBuildCombinedOutput(args.Output, []string{args.Program}, args.BuildFlags.value)
   993  		case "test":
   994  			cmd, out, err = gobuild.GoTestBuildCombinedOutput(args.Output, []string{args.Program}, args.BuildFlags.value)
   995  		}
   996  		args.DlvCwd, _ = filepath.Abs(args.DlvCwd)
   997  		s.config.log.Debugf("building from %q: [%s]", args.DlvCwd, cmd)
   998  		if err != nil {
   999  			if deleteOnError {
  1000  				gobuild.Remove(args.Output)
  1001  			}
  1002  			s.send(&dap.OutputEvent{
  1003  				Event: *newEvent("output"),
  1004  				Body: dap.OutputEventBody{
  1005  					Output:   fmt.Sprintf("Build Error: %s\n%s (%s)\n", cmd, strings.TrimSpace(string(out)), err.Error()),
  1006  					Category: "stderr",
  1007  				},
  1008  			})
  1009  			// Users are used to checking the Debug Console for build errors.
  1010  			// No need to bother them with a visible pop-up.
  1011  			s.sendErrorResponse(request.Request, FailedToLaunch, "Failed to launch",
  1012  				"Build error: Check the debug console for details.")
  1013  			return
  1014  		}
  1015  		s.mu.Lock()
  1016  		s.binaryToRemove = args.Output
  1017  		s.mu.Unlock()
  1018  	}
  1019  	s.config.ProcessArgs = append([]string{debugbinary}, args.Args...)
  1020  
  1021  	s.setLaunchAttachArgs(args.LaunchAttachCommonConfig)
  1022  
  1023  	if args.Cwd == "" {
  1024  		if args.Mode == "test" {
  1025  			// In test mode, run the test binary from the package directory
  1026  			// like in `go test` and `dlv test` by default.
  1027  			args.Cwd = s.getPackageDir(args.Program)
  1028  		} else {
  1029  			args.Cwd = "."
  1030  		}
  1031  	}
  1032  	s.config.Debugger.WorkingDir = args.Cwd
  1033  
  1034  	// Backend layers will interpret paths relative to server's working directory:
  1035  	// reflect that before logging.
  1036  	argsToLog := args
  1037  	argsToLog.Program, _ = filepath.Abs(args.Program)
  1038  	argsToLog.Cwd, _ = filepath.Abs(args.Cwd)
  1039  	s.config.log.Debugf("launching binary '%s' with config: %s", debugbinary, prettyPrint(argsToLog))
  1040  
  1041  	redirected := false
  1042  	switch args.OutputMode {
  1043  	case "remote":
  1044  		redirected = true
  1045  	case "local", "":
  1046  		// noting
  1047  	default:
  1048  		s.sendShowUserErrorResponse(request.Request, FailedToLaunch, "Failed to launch",
  1049  			fmt.Sprintf("invalid debug configuration - unsupported 'outputMode' attribute %q", args.OutputMode))
  1050  		return
  1051  	}
  1052  
  1053  	redirectedFunc := func(stdoutReader io.ReadCloser, stderrReader io.ReadCloser) {
  1054  		runReadFunc := func(reader io.ReadCloser, category string) {
  1055  			defer s.preTerminatedWG.Done()
  1056  			defer reader.Close()
  1057  			// Read output from `reader` and send to client
  1058  			var out [1024]byte
  1059  			for {
  1060  				n, err := reader.Read(out[:])
  1061  				if n > 0 {
  1062  					outs := string(out[:n])
  1063  					s.send(&dap.OutputEvent{
  1064  						Event: *newEvent("output"),
  1065  						Body: dap.OutputEventBody{
  1066  							Output:   outs,
  1067  							Category: category,
  1068  						},
  1069  					})
  1070  				}
  1071  				if err != nil {
  1072  					if err == io.EOF {
  1073  						return
  1074  					}
  1075  					s.config.log.Errorf("failed read by %s - %v ", category, err)
  1076  					return
  1077  				}
  1078  			}
  1079  		}
  1080  
  1081  		s.preTerminatedWG.Add(2)
  1082  		go runReadFunc(stdoutReader, "stdout")
  1083  		go runReadFunc(stderrReader, "stderr")
  1084  	}
  1085  
  1086  	if args.NoDebug {
  1087  		s.mu.Lock()
  1088  		cmd, err := s.newNoDebugProcess(debugbinary, args.Args, s.config.Debugger.WorkingDir, redirected)
  1089  		s.mu.Unlock()
  1090  		if err != nil {
  1091  			s.sendShowUserErrorResponse(request.Request, FailedToLaunch, "Failed to launch", err.Error())
  1092  			return
  1093  		}
  1094  		// Skip 'initialized' event, which will prevent the client from sending
  1095  		// debug-related requests.
  1096  		s.send(&dap.LaunchResponse{Response: *newResponse(request.Request)})
  1097  
  1098  		// Start the program on a different goroutine, so we can listen for disconnect request.
  1099  		go func() {
  1100  			if redirected {
  1101  				redirectedFunc(s.stdoutReader, s.stderrReader)
  1102  			}
  1103  
  1104  			if err := cmd.Wait(); err != nil {
  1105  				s.config.log.Debugf("program exited with error: %v", err)
  1106  			}
  1107  
  1108  			close(s.noDebugProcess.exited)
  1109  			s.logToConsole(proc.ErrProcessExited{Pid: cmd.ProcessState.Pid(), Status: cmd.ProcessState.ExitCode()}.Error())
  1110  			s.send(&dap.TerminatedEvent{Event: *newEvent("terminated")})
  1111  		}()
  1112  		return
  1113  	}
  1114  
  1115  	var closeAll func()
  1116  	if redirected {
  1117  		var (
  1118  			readers         [2]io.ReadCloser
  1119  			outputRedirects [2]proc.OutputRedirect
  1120  		)
  1121  
  1122  		for i := 0; i < 2; i++ {
  1123  			readers[i], outputRedirects[i], err = proc.Redirector()
  1124  			if err != nil {
  1125  				s.sendShowUserErrorResponse(request.Request, InternalError, "Internal Error",
  1126  					fmt.Sprintf("failed to generate stdio pipes - %v", err))
  1127  				return
  1128  			}
  1129  		}
  1130  
  1131  		s.config.Debugger.Stdout = outputRedirects[0]
  1132  		s.config.Debugger.Stderr = outputRedirects[1]
  1133  
  1134  		redirectedFunc(readers[0], readers[1])
  1135  		closeAll = func() {
  1136  			for index := range readers {
  1137  				if closeErr := readers[index].Close(); closeErr != nil {
  1138  					s.config.log.Warnf("failed to clear redirects - %v", closeErr)
  1139  				}
  1140  			}
  1141  		}
  1142  	}
  1143  
  1144  	func() {
  1145  		s.mu.Lock()
  1146  		defer s.mu.Unlock() // Make sure to unlock in case of panic that will become internal error
  1147  		s.debugger, err = debugger.New(&s.config.Debugger, s.config.ProcessArgs)
  1148  	}()
  1149  	if err != nil {
  1150  		if s.binaryToRemove != "" {
  1151  			gobuild.Remove(s.binaryToRemove)
  1152  		}
  1153  		s.sendShowUserErrorResponse(request.Request, FailedToLaunch, "Failed to launch", err.Error())
  1154  		if closeAll != nil {
  1155  			closeAll()
  1156  		}
  1157  		return
  1158  	}
  1159  	// Enable StepBack controls on supported backends
  1160  	if s.config.Debugger.Backend == "rr" {
  1161  		s.send(&dap.CapabilitiesEvent{Event: *newEvent("capabilities"), Body: dap.CapabilitiesEventBody{Capabilities: dap.Capabilities{SupportsStepBack: true}}})
  1162  	}
  1163  
  1164  	// Notify the client that the debugger is ready to start accepting
  1165  	// configuration requests for setting breakpoints, etc. The client
  1166  	// will end the configuration sequence with 'configurationDone'.
  1167  	s.send(&dap.InitializedEvent{Event: *newEvent("initialized")})
  1168  	s.send(&dap.LaunchResponse{Response: *newResponse(request.Request)})
  1169  }
  1170  
  1171  func (s *Session) getPackageDir(pkg string) string {
  1172  	cmd := exec.Command("go", "list", "-f", "{{.Dir}}", pkg)
  1173  	out, err := cmd.Output()
  1174  	if err != nil {
  1175  		s.config.log.Debugf("failed to determine package directory for %v: %v\n%s", pkg, err, out)
  1176  		return "."
  1177  	}
  1178  	return string(bytes.TrimSpace(out))
  1179  }
  1180  
  1181  // newNoDebugProcess is called from onLaunchRequest (run goroutine) and
  1182  // requires holding mu lock. It prepares process exec.Cmd to be started.
  1183  func (s *Session) newNoDebugProcess(program string, targetArgs []string, wd string, redirected bool) (cmd *exec.Cmd, err error) {
  1184  	if s.noDebugProcess != nil {
  1185  		return nil, fmt.Errorf("another launch request is in progress")
  1186  	}
  1187  
  1188  	cmd = exec.Command(program, targetArgs...)
  1189  	cmd.Stdin, cmd.Dir = os.Stdin, wd
  1190  
  1191  	if redirected {
  1192  		if s.stderrReader, err = cmd.StderrPipe(); err != nil {
  1193  			return nil, err
  1194  		}
  1195  
  1196  		if s.stdoutReader, err = cmd.StdoutPipe(); err != nil {
  1197  			return nil, err
  1198  		}
  1199  	} else {
  1200  		cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
  1201  	}
  1202  
  1203  	if err = cmd.Start(); err != nil {
  1204  		return nil, err
  1205  	}
  1206  
  1207  	s.noDebugProcess = &process{Cmd: cmd, exited: make(chan struct{})}
  1208  	return cmd, nil
  1209  }
  1210  
  1211  // stopNoDebugProcess is called from Stop (main goroutine) and
  1212  // onDisconnectRequest (run goroutine) and requires holding mu lock.
  1213  func (s *Session) stopNoDebugProcess() {
  1214  	if s.noDebugProcess == nil {
  1215  		// We already handled termination or there was never a process
  1216  		return
  1217  	}
  1218  	select {
  1219  	case <-s.noDebugProcess.exited:
  1220  		s.noDebugProcess = nil
  1221  		return
  1222  	default:
  1223  	}
  1224  
  1225  	// TODO(hyangah): gracefully terminate the process and its children processes.
  1226  	s.logToConsole(fmt.Sprintf("Terminating process %d", s.noDebugProcess.Process.Pid))
  1227  	s.noDebugProcess.Process.Kill() // Don't check error. Process killing and self-termination may race.
  1228  
  1229  	// Wait for kill to complete or time out
  1230  	select {
  1231  	case <-time.After(5 * time.Second):
  1232  		s.config.log.Debug("noDebug process kill timed out")
  1233  	case <-s.noDebugProcess.exited:
  1234  		s.config.log.Debug("noDebug process killed")
  1235  		s.noDebugProcess = nil
  1236  	}
  1237  }
  1238  
  1239  // onDisconnectRequest handles the DisconnectRequest. Per the DAP spec,
  1240  // it disconnects the debuggee and signals that the debug adaptor
  1241  // (in our case this TCP server) can be terminated.
  1242  func (s *Session) onDisconnectRequest(request *dap.DisconnectRequest) {
  1243  	s.mu.Lock()
  1244  	defer s.mu.Unlock()
  1245  
  1246  	if s.debugger != nil && s.config.AcceptMulti && (request.Arguments == nil || !request.Arguments.TerminateDebuggee) {
  1247  		// This is a multi-use server/debugger, so a disconnect request that doesn't
  1248  		// terminate the debuggee should clean up only the client connection and pointer to debugger,
  1249  		// but not the entire server.
  1250  		status := "halted"
  1251  		if s.isRunningCmd() {
  1252  			status = "running"
  1253  		} else if state, err := s.debugger.State(false); processExited(state, err) {
  1254  			status = "exited"
  1255  			s.preTerminatedWG.Wait()
  1256  		}
  1257  
  1258  		s.logToConsole(fmt.Sprintf("Closing client session, but leaving multi-client DAP server at %s with debuggee %s", s.config.Listener.Addr().String(), status))
  1259  		s.send(&dap.DisconnectResponse{Response: *newResponse(request.Request)})
  1260  		s.send(&dap.TerminatedEvent{Event: *newEvent("terminated")})
  1261  		s.conn.Close()
  1262  		s.debugger = nil
  1263  		// The target is left in whatever state it is already in - halted or running.
  1264  		// The users therefore have the flexibility to choose the appropriate state
  1265  		// for their case before disconnecting. This is also desirable in case of
  1266  		// the client connection fails unexpectedly and the user needs to reconnect.
  1267  		// TODO(polina): should we always issue a continue here if it is not running
  1268  		// like is done in vscode-go legacy adapter?
  1269  		// Ideally we want to use bool suspendDebuggee flag, but it is not yet
  1270  		// available in vscode: https://github.com/microsoft/vscode/issues/134412
  1271  		return
  1272  	}
  1273  
  1274  	defer s.config.triggerServerStop()
  1275  	var err error
  1276  	if s.debugger != nil {
  1277  		// We always kill launched programs.
  1278  		// In case of attach, we leave the program
  1279  		// running by default, which can be
  1280  		// overridden by an explicit request to terminate.
  1281  		killProcess := s.debugger.AttachPid() == 0 || (request.Arguments != nil && request.Arguments.TerminateDebuggee)
  1282  		err = s.stopDebugSession(killProcess)
  1283  	} else if s.noDebugProcess != nil {
  1284  		s.stopNoDebugProcess()
  1285  	}
  1286  	if err != nil {
  1287  		s.sendErrorResponse(request.Request, DisconnectError, "Error while disconnecting", err.Error())
  1288  	} else {
  1289  		s.send(&dap.DisconnectResponse{Response: *newResponse(request.Request)})
  1290  	}
  1291  	s.preTerminatedWG.Wait()
  1292  	// The debugging session has ended, so we send a terminated event.
  1293  	s.send(&dap.TerminatedEvent{Event: *newEvent("terminated")})
  1294  }
  1295  
  1296  // stopDebugSession is called from Stop (main goroutine) and
  1297  // onDisconnectRequest (run goroutine) and requires holding mu lock.
  1298  // Returns any detach error other than proc.ErrProcessExited.
  1299  func (s *Session) stopDebugSession(killProcess bool) error {
  1300  	s.changeStateMu.Lock()
  1301  	defer func() {
  1302  		// Avoid running stop sequence twice.
  1303  		// It's not fatal, but will result in duplicate logging.
  1304  		s.debugger = nil
  1305  		s.changeStateMu.Unlock()
  1306  	}()
  1307  	if s.debugger == nil {
  1308  		return nil
  1309  	}
  1310  	var err error
  1311  	var exited error
  1312  	// Halting will stop any debugger command that's pending on another
  1313  	// per-request goroutine. Tell auto-resumer not to resume, so the
  1314  	// goroutine can wrap-up and exit.
  1315  	s.setHaltRequested(true)
  1316  	state, err := s.halt()
  1317  	if errors.Is(err, proc.ErrProcessDetached) {
  1318  		s.config.log.Debug("halt returned error: ", err)
  1319  		return nil
  1320  	}
  1321  	if err != nil {
  1322  		var errProcessExited proc.ErrProcessExited
  1323  		switch {
  1324  		case errors.As(err, &errProcessExited):
  1325  			exited = errProcessExited
  1326  		default:
  1327  			s.config.log.Error("halt returned error: ", err)
  1328  			if err.Error() == "no such process" {
  1329  				exited = err
  1330  			}
  1331  		}
  1332  	} else if state.Exited {
  1333  		exited = proc.ErrProcessExited{Pid: s.debugger.ProcessPid(), Status: state.ExitStatus}
  1334  		s.config.log.Debug("halt returned state: ", exited)
  1335  	}
  1336  	if exited != nil {
  1337  		// TODO(suzmue): log exited error when the process exits, which may have been before
  1338  		// halt was called.
  1339  		s.logToConsole(exited.Error())
  1340  		s.logToConsole("Detaching")
  1341  	} else if killProcess {
  1342  		s.logToConsole("Detaching and terminating target process")
  1343  	} else {
  1344  		s.logToConsole("Detaching without terminating target process")
  1345  	}
  1346  	err = s.debugger.Detach(killProcess)
  1347  	if err != nil {
  1348  		var errProcessExited proc.ErrProcessExited
  1349  		switch {
  1350  		case errors.As(err, &errProcessExited):
  1351  			s.config.log.Debug(errProcessExited)
  1352  			if exited != nil {
  1353  				s.logToConsole(exited.Error())
  1354  			}
  1355  			err = nil
  1356  		default:
  1357  			s.config.log.Error("detach returned error: ", err)
  1358  		}
  1359  	}
  1360  	return err
  1361  }
  1362  
  1363  // halt sends a halt request if the debuggee is running.
  1364  // changeStateMu should be held when calling (*Server).halt.
  1365  func (s *Session) halt() (*api.DebuggerState, error) {
  1366  	s.config.log.Debug("halting")
  1367  	// Only send a halt request if the debuggee is running.
  1368  	if s.debugger.IsRunning() {
  1369  		return s.debugger.Command(&api.DebuggerCommand{Name: api.Halt}, nil)
  1370  	}
  1371  	s.config.log.Debug("process not running")
  1372  	return s.debugger.State(false)
  1373  }
  1374  
  1375  func (s *Session) isNoDebug() bool {
  1376  	s.mu.Lock()
  1377  	defer s.mu.Unlock()
  1378  	return s.noDebugProcess != nil
  1379  }
  1380  
  1381  func (s *Session) onSetBreakpointsRequest(request *dap.SetBreakpointsRequest) {
  1382  	if request.Arguments.Source.Path == "" {
  1383  		s.sendErrorResponse(request.Request, UnableToSetBreakpoints, "Unable to set or clear breakpoints", "empty file path")
  1384  		return
  1385  	}
  1386  
  1387  	clientPath := request.Arguments.Source.Path
  1388  	serverPath := s.toServerPath(clientPath)
  1389  
  1390  	// Get all existing breakpoints that match for this source.
  1391  	sourceRequestPrefix := fmt.Sprintf("sourceBp Path=%q ", request.Arguments.Source.Path)
  1392  
  1393  	breakpoints := s.setBreakpoints(sourceRequestPrefix, len(request.Arguments.Breakpoints), func(i int) *bpMetadata {
  1394  		want := request.Arguments.Breakpoints[i]
  1395  		return &bpMetadata{
  1396  			name:         fmt.Sprintf("%s Line=%d Column=%d", sourceRequestPrefix, want.Line, want.Column),
  1397  			condition:    want.Condition,
  1398  			hitCondition: want.HitCondition,
  1399  			logMessage:   want.LogMessage,
  1400  		}
  1401  	}, func(i int) (*bpLocation, error) {
  1402  		want := request.Arguments.Breakpoints[i]
  1403  		return &bpLocation{
  1404  			file: serverPath,
  1405  			line: want.Line,
  1406  		}, nil
  1407  	})
  1408  
  1409  	response := &dap.SetBreakpointsResponse{Response: *newResponse(request.Request)}
  1410  	response.Body.Breakpoints = breakpoints
  1411  
  1412  	s.send(response)
  1413  }
  1414  
  1415  type bpMetadata struct {
  1416  	name         string
  1417  	condition    string
  1418  	hitCondition string
  1419  	logMessage   string
  1420  }
  1421  
  1422  type bpLocation struct {
  1423  	file  string
  1424  	line  int
  1425  	addr  uint64
  1426  	addrs []uint64
  1427  }
  1428  
  1429  // setBreakpoints is a helper function for setting source, function and instruction
  1430  // breakpoints. It takes the prefix of the name for all breakpoints that should be
  1431  // included, the total number of breakpoints, and functions for computing the metadata
  1432  // and the location. The location is computed separately because this may be more
  1433  // expensive to compute and may not always be necessary.
  1434  func (s *Session) setBreakpoints(prefix string, totalBps int, metadataFunc func(i int) *bpMetadata, locFunc func(i int) (*bpLocation, error)) []dap.Breakpoint {
  1435  	// If a breakpoint:
  1436  	// -- exists and not in request => ClearBreakpoint
  1437  	// -- exists and in request => AmendBreakpoint
  1438  	// -- doesn't exist and in request => SetBreakpoint
  1439  
  1440  	// Get all existing breakpoints matching the prefix.
  1441  	existingBps := s.getMatchingBreakpoints(prefix)
  1442  
  1443  	// createdBps is a set of breakpoint names that have been added
  1444  	// during this request. This is used to catch duplicate set
  1445  	// breakpoints requests and to track which breakpoints need to
  1446  	// be deleted.
  1447  	createdBps := make(map[string]struct{}, len(existingBps))
  1448  
  1449  	breakpoints := make([]dap.Breakpoint, totalBps)
  1450  	// Amend existing breakpoints.
  1451  	for i := 0; i < totalBps; i++ {
  1452  		want := metadataFunc(i)
  1453  		got, ok := existingBps[want.name]
  1454  		if got == nil || !ok {
  1455  			// Skip if the breakpoint does not already exist.
  1456  			continue
  1457  		}
  1458  
  1459  		var err error
  1460  		if _, ok := createdBps[want.name]; ok {
  1461  			err = fmt.Errorf("breakpoint already exists")
  1462  		} else {
  1463  			got.Disabled = false
  1464  			got.Cond = want.condition
  1465  			got.HitCond = want.hitCondition
  1466  			err = setLogMessage(got, want.logMessage)
  1467  			if err == nil {
  1468  				err = s.debugger.AmendBreakpoint(got)
  1469  			}
  1470  		}
  1471  		createdBps[want.name] = struct{}{}
  1472  		s.updateBreakpointsResponse(breakpoints, i, err, got)
  1473  	}
  1474  
  1475  	// Clear breakpoints.
  1476  	// Any breakpoint that existed before this request but was not amended must be deleted.
  1477  	s.clearBreakpoints(existingBps, createdBps)
  1478  
  1479  	// Add new breakpoints.
  1480  	for i := 0; i < totalBps; i++ {
  1481  		want := metadataFunc(i)
  1482  		if _, ok := existingBps[want.name]; ok {
  1483  			continue
  1484  		}
  1485  
  1486  		var got *api.Breakpoint
  1487  		wantLoc, err := locFunc(i)
  1488  		if err == nil {
  1489  			if _, ok := createdBps[want.name]; ok {
  1490  				err = fmt.Errorf("breakpoint already exists")
  1491  			} else {
  1492  				bp := &api.Breakpoint{
  1493  					Name:    want.name,
  1494  					File:    wantLoc.file,
  1495  					Line:    wantLoc.line,
  1496  					Addr:    wantLoc.addr,
  1497  					Addrs:   wantLoc.addrs,
  1498  					Cond:    want.condition,
  1499  					HitCond: want.hitCondition,
  1500  				}
  1501  				err = setLogMessage(bp, want.logMessage)
  1502  				if err == nil {
  1503  					// Create new breakpoints.
  1504  					got, err = s.debugger.CreateBreakpoint(bp, "", nil, false)
  1505  				}
  1506  			}
  1507  		}
  1508  		createdBps[want.name] = struct{}{}
  1509  		s.updateBreakpointsResponse(breakpoints, i, err, got)
  1510  	}
  1511  	return breakpoints
  1512  }
  1513  
  1514  func setLogMessage(bp *api.Breakpoint, msg string) error {
  1515  	tracepoint, userdata, err := parseLogPoint(msg)
  1516  	if err != nil {
  1517  		return err
  1518  	}
  1519  	bp.Tracepoint = tracepoint
  1520  	if userdata != nil {
  1521  		bp.UserData = *userdata
  1522  	}
  1523  	return nil
  1524  }
  1525  
  1526  func (s *Session) updateBreakpointsResponse(breakpoints []dap.Breakpoint, i int, err error, got *api.Breakpoint) {
  1527  	breakpoints[i].Verified = err == nil
  1528  	if err != nil {
  1529  		breakpoints[i].Message = err.Error()
  1530  	} else {
  1531  		path := s.toClientPath(got.File)
  1532  		breakpoints[i].Id = got.ID
  1533  		breakpoints[i].Line = got.Line
  1534  		breakpoints[i].Source = &dap.Source{Name: filepath.Base(path), Path: path}
  1535  	}
  1536  }
  1537  
  1538  // functionBpPrefix is the prefix of bp.Name for every breakpoint bp set
  1539  // in this request.
  1540  const functionBpPrefix = "functionBreakpoint"
  1541  
  1542  func (s *Session) onSetFunctionBreakpointsRequest(request *dap.SetFunctionBreakpointsRequest) {
  1543  	breakpoints := s.setBreakpoints(functionBpPrefix, len(request.Arguments.Breakpoints), func(i int) *bpMetadata {
  1544  		want := request.Arguments.Breakpoints[i]
  1545  		return &bpMetadata{
  1546  			name:         fmt.Sprintf("%s Name=%s", functionBpPrefix, want.Name),
  1547  			condition:    want.Condition,
  1548  			hitCondition: want.HitCondition,
  1549  			logMessage:   "",
  1550  		}
  1551  	}, func(i int) (*bpLocation, error) {
  1552  		want := request.Arguments.Breakpoints[i]
  1553  		// Set the function breakpoint
  1554  		spec, err := locspec.Parse(want.Name)
  1555  		if err != nil {
  1556  			return nil, err
  1557  		}
  1558  		if loc, ok := spec.(*locspec.NormalLocationSpec); !ok || loc.FuncBase == nil {
  1559  			// Other locations do not make sense in the context of function breakpoints.
  1560  			// Regex locations are likely to resolve to multiple places and offset locations
  1561  			// are only meaningful at the time the breakpoint was created.
  1562  			return nil, fmt.Errorf("breakpoint name %q could not be parsed as a function. name must be in the format 'funcName', 'funcName:line' or 'fileName:line'", want.Name)
  1563  		}
  1564  
  1565  		if want.Name[0] == '.' {
  1566  			return nil, fmt.Errorf("breakpoint names that are relative paths are not supported")
  1567  		}
  1568  		// Find the location of the function name. CreateBreakpoint requires the name to include the base
  1569  		// (e.g. main.functionName is supported but not functionName).
  1570  		// We first find the location of the function, and then set breakpoints for that location.
  1571  		var locs []api.Location
  1572  		locs, err = s.debugger.FindLocationSpec(-1, 0, 0, want.Name, spec, true, s.args.substitutePathClientToServer)
  1573  		if err != nil {
  1574  			return nil, err
  1575  		}
  1576  		if len(locs) == 0 {
  1577  			return nil, err
  1578  		}
  1579  		if len(locs) > 1 {
  1580  			s.config.log.Debugf("multiple locations found for %s", want.Name)
  1581  		}
  1582  
  1583  		// Set breakpoint using the PCs that were found.
  1584  		loc := locs[0]
  1585  		return &bpLocation{addr: loc.PC, addrs: loc.PCs}, nil
  1586  	})
  1587  
  1588  	response := &dap.SetFunctionBreakpointsResponse{Response: *newResponse(request.Request)}
  1589  	response.Body.Breakpoints = breakpoints
  1590  
  1591  	s.send(response)
  1592  }
  1593  
  1594  const instructionBpPrefix = "instructionBreakpoint"
  1595  
  1596  func (s *Session) onSetInstructionBreakpointsRequest(request *dap.SetInstructionBreakpointsRequest) {
  1597  	breakpoints := s.setBreakpoints(instructionBpPrefix, len(request.Arguments.Breakpoints), func(i int) *bpMetadata {
  1598  		want := request.Arguments.Breakpoints[i]
  1599  		return &bpMetadata{
  1600  			name:         fmt.Sprintf("%s PC=%s", instructionBpPrefix, want.InstructionReference),
  1601  			condition:    want.Condition,
  1602  			hitCondition: want.HitCondition,
  1603  			logMessage:   "",
  1604  		}
  1605  	}, func(i int) (*bpLocation, error) {
  1606  		want := request.Arguments.Breakpoints[i]
  1607  		addr, err := strconv.ParseInt(want.InstructionReference, 0, 64)
  1608  		if err != nil {
  1609  			return nil, err
  1610  		}
  1611  		return &bpLocation{addr: uint64(addr)}, nil
  1612  	})
  1613  
  1614  	response := &dap.SetInstructionBreakpointsResponse{Response: *newResponse(request.Request)}
  1615  	response.Body.Breakpoints = breakpoints
  1616  	s.send(response)
  1617  }
  1618  
  1619  func (s *Session) clearBreakpoints(existingBps map[string]*api.Breakpoint, amendedBps map[string]struct{}) error {
  1620  	for req, bp := range existingBps {
  1621  		if _, ok := amendedBps[req]; ok {
  1622  			continue
  1623  		}
  1624  		_, err := s.debugger.ClearBreakpoint(bp)
  1625  		if err != nil {
  1626  			return err
  1627  		}
  1628  	}
  1629  	return nil
  1630  }
  1631  
  1632  func (s *Session) getMatchingBreakpoints(prefix string) map[string]*api.Breakpoint {
  1633  	existing := s.debugger.Breakpoints(false)
  1634  	matchingBps := make(map[string]*api.Breakpoint, len(existing))
  1635  	for _, bp := range existing {
  1636  		// Skip special breakpoints such as for panic.
  1637  		if bp.ID < 0 {
  1638  			continue
  1639  		}
  1640  		// Skip breakpoints that do not meet the condition.
  1641  		if !strings.HasPrefix(bp.Name, prefix) {
  1642  			continue
  1643  		}
  1644  		matchingBps[bp.Name] = bp
  1645  	}
  1646  	return matchingBps
  1647  }
  1648  
  1649  func (s *Session) onSetExceptionBreakpointsRequest(request *dap.SetExceptionBreakpointsRequest) {
  1650  	// Unlike what DAP documentation claims, this request is always sent
  1651  	// even though we specified no filters at initialization. Handle as no-op.
  1652  	s.send(&dap.SetExceptionBreakpointsResponse{Response: *newResponse(request.Request)})
  1653  }
  1654  
  1655  func closeIfOpen(ch chan struct{}) {
  1656  	if ch != nil {
  1657  		select {
  1658  		case <-ch:
  1659  			// already closed
  1660  		default:
  1661  			close(ch)
  1662  		}
  1663  	}
  1664  }
  1665  
  1666  // onConfigurationDoneRequest handles 'configurationDone' request.
  1667  // This is an optional request enabled by capability 'supportsConfigurationDoneRequest'.
  1668  // It gets triggered after all the debug requests that follow initialized event,
  1669  // so the s.debugger is guaranteed to be set. Expects the target to be halted.
  1670  func (s *Session) onConfigurationDoneRequest(request *dap.ConfigurationDoneRequest, allowNextStateChange *syncflag) {
  1671  	defer allowNextStateChange.raise()
  1672  	if s.args.stopOnEntry {
  1673  		e := &dap.StoppedEvent{
  1674  			Event: *newEvent("stopped"),
  1675  			Body:  dap.StoppedEventBody{Reason: "entry", ThreadId: 1, AllThreadsStopped: true},
  1676  		}
  1677  		s.send(e)
  1678  	}
  1679  	s.debugger.TargetGroup().KeepSteppingBreakpoints = proc.HaltKeepsSteppingBreakpoints | proc.TracepointKeepsSteppingBreakpoints
  1680  
  1681  	s.logToConsole("Type 'dlv help' for list of commands.")
  1682  	s.send(&dap.ConfigurationDoneResponse{Response: *newResponse(request.Request)})
  1683  
  1684  	if !s.args.stopOnEntry {
  1685  		s.runUntilStopAndNotify(api.Continue, allowNextStateChange)
  1686  	}
  1687  }
  1688  
  1689  // onContinueRequest handles 'continue' request.
  1690  // This is a mandatory request to support.
  1691  func (s *Session) onContinueRequest(request *dap.ContinueRequest, allowNextStateChange *syncflag) {
  1692  	s.send(&dap.ContinueResponse{
  1693  		Response: *newResponse(request.Request),
  1694  		Body:     dap.ContinueResponseBody{AllThreadsContinued: true},
  1695  	})
  1696  	s.runUntilStopAndNotify(api.Continue, allowNextStateChange)
  1697  }
  1698  
  1699  func fnName(loc *proc.Location) string {
  1700  	if loc.Fn == nil {
  1701  		return "???"
  1702  	}
  1703  	fullSymbol := loc.Fn.Name
  1704  	packagePath := loc.Fn.PackageName()
  1705  	lastSlash := strings.LastIndex(packagePath, "/")
  1706  	if lastSlash >= 0 {
  1707  		// strip everything until the last slash from the package path
  1708  		return fullSymbol[lastSlash+1:]
  1709  	}
  1710  
  1711  	// We either have no package name at all, or it doesn't contain a slash:
  1712  	// return name unchanged
  1713  	return fullSymbol
  1714  }
  1715  
  1716  func fnPackageName(loc *proc.Location) string {
  1717  	if loc.Fn == nil {
  1718  		// attribute unknown functions to the runtime
  1719  		return "runtime"
  1720  	}
  1721  	return loc.Fn.PackageName()
  1722  }
  1723  
  1724  // onThreadsRequest handles 'threads' request.
  1725  // This is a mandatory request to support.
  1726  // It is sent in response to configurationDone response and stopped events.
  1727  // Depending on the debug session stage, goroutines information
  1728  // might not be available. However, the DAP spec states that
  1729  // "even if a debug adapter does not support multiple threads,
  1730  // it must implement the threads request and return a single
  1731  // (dummy) thread". Therefore, this handler never returns
  1732  // an error response. If the dummy thread is returned in its place,
  1733  // the next waterfall request for its stackTrace will return the error.
  1734  func (s *Session) onThreadsRequest(request *dap.ThreadsRequest) {
  1735  	var err error
  1736  	var gs []*proc.G
  1737  	var next int
  1738  	if s.debugger != nil {
  1739  		gs, next, err = s.debugger.Goroutines(0, maxGoroutines)
  1740  		if err == nil {
  1741  			// Parse the goroutine arguments.
  1742  			filters, _, _, _, _, _, _, parseErr := api.ParseGoroutineArgs(s.args.GoroutineFilters)
  1743  			if parseErr != nil {
  1744  				s.logToConsole(parseErr.Error())
  1745  			}
  1746  			if s.args.HideSystemGoroutines {
  1747  				filters = append(filters, api.ListGoroutinesFilter{
  1748  					Kind:    api.GoroutineUser,
  1749  					Negated: false,
  1750  				})
  1751  			}
  1752  			gs = s.debugger.FilterGoroutines(gs, filters)
  1753  		}
  1754  	}
  1755  
  1756  	var threads []dap.Thread
  1757  	if err != nil {
  1758  		var errProcessExited proc.ErrProcessExited
  1759  		switch {
  1760  		case errors.As(err, &errProcessExited):
  1761  			// If the program exits very quickly, the initial threads request will complete after it has exited.
  1762  			// A TerminatedEvent has already been sent. Ignore the error returned in this case.
  1763  			s.config.log.Debug(errProcessExited)
  1764  		default:
  1765  			s.send(&dap.OutputEvent{
  1766  				Event: *newEvent("output"),
  1767  				Body: dap.OutputEventBody{
  1768  					Output:   fmt.Sprintf("Unable to retrieve goroutines: %s\n", err.Error()),
  1769  					Category: "stderr",
  1770  				},
  1771  			})
  1772  		}
  1773  		threads = []dap.Thread{{Id: 1, Name: "Dummy"}}
  1774  	} else if len(gs) == 0 {
  1775  		threads = []dap.Thread{{Id: 1, Name: "Dummy"}}
  1776  	} else {
  1777  		state, err := s.debugger.State( /*nowait*/ true)
  1778  		if err != nil {
  1779  			s.config.log.Debug("Unable to get debugger state: ", err)
  1780  		}
  1781  
  1782  		if next >= 0 {
  1783  			s.logToConsole(fmt.Sprintf("Too many goroutines, only loaded %d", len(gs)))
  1784  
  1785  			// Make sure the selected goroutine is included in the list of threads
  1786  			// to return.
  1787  			if state != nil && state.SelectedGoroutine != nil {
  1788  				var selectedFound bool
  1789  				for _, g := range gs {
  1790  					if g.ID == state.SelectedGoroutine.ID {
  1791  						selectedFound = true
  1792  						break
  1793  					}
  1794  				}
  1795  				if !selectedFound {
  1796  					g, err := s.debugger.FindGoroutine(state.SelectedGoroutine.ID)
  1797  					if err != nil {
  1798  						s.config.log.Debug("Error getting selected goroutine: ", err)
  1799  					} else {
  1800  						// TODO(suzmue): Consider putting the selected goroutine at the top.
  1801  						// To be consistent we may want to do this for all threads requests.
  1802  						gs = append(gs, g)
  1803  					}
  1804  				}
  1805  			}
  1806  		}
  1807  
  1808  		threads = make([]dap.Thread, len(gs))
  1809  		s.debugger.LockTarget()
  1810  		defer s.debugger.UnlockTarget()
  1811  
  1812  		for i, g := range gs {
  1813  			selected := ""
  1814  			if state != nil && state.SelectedGoroutine != nil && g.ID == state.SelectedGoroutine.ID {
  1815  				selected = "* "
  1816  			}
  1817  			thread := ""
  1818  			if g.Thread != nil && g.Thread.ThreadID() != 0 {
  1819  				thread = fmt.Sprintf(" (Thread %d)", g.Thread.ThreadID())
  1820  			}
  1821  			var labels strings.Builder
  1822  			writeLabelsForKeys := func(keys []string) {
  1823  				for _, k := range keys {
  1824  					labelValue := g.Labels()[k]
  1825  					if labelValue != "" {
  1826  						labels.WriteByte(' ')
  1827  						labels.WriteString(k)
  1828  						labels.WriteByte(':')
  1829  						labels.WriteString(labelValue)
  1830  					}
  1831  				}
  1832  			}
  1833  			if len(s.args.ShowPprofLabels) == 1 {
  1834  				labelKey := s.args.ShowPprofLabels[0]
  1835  				if labelKey == "*" {
  1836  					keys := make([]string, 0, len(g.Labels()))
  1837  					for k := range g.Labels() {
  1838  						keys = append(keys, k)
  1839  					}
  1840  					sort.Strings(keys)
  1841  					writeLabelsForKeys(keys)
  1842  				} else {
  1843  					labelValue := g.Labels()[labelKey]
  1844  					if labelValue != "" {
  1845  						labels.WriteByte(' ')
  1846  						labels.WriteString(labelValue)
  1847  					}
  1848  				}
  1849  			} else {
  1850  				writeLabelsForKeys(s.args.ShowPprofLabels)
  1851  			}
  1852  			// File name and line number are communicated via `stackTrace`
  1853  			// so no need to include them here.
  1854  			loc := g.UserCurrent()
  1855  			threads[i].Name = fmt.Sprintf("%s[Go %d%s] %s%s", selected, g.ID, labels.String(), fnName(&loc), thread)
  1856  			threads[i].Id = int(g.ID)
  1857  		}
  1858  	}
  1859  
  1860  	response := &dap.ThreadsResponse{
  1861  		Response: *newResponse(request.Request),
  1862  		Body:     dap.ThreadsResponseBody{Threads: threads},
  1863  	}
  1864  	s.send(response)
  1865  }
  1866  
  1867  // onAttachRequest handles 'attach' request.
  1868  // This is a mandatory request to support.
  1869  // Attach debug sessions support the following modes:
  1870  //
  1871  //   - [DEFAULT] "local" -- attaches debugger to a local running process.
  1872  //     Required args: processID
  1873  //   - "remote" -- attaches client to a debugger already attached to a process.
  1874  //     Required args: none (host/port are used externally to connect)
  1875  func (s *Session) onAttachRequest(request *dap.AttachRequest) {
  1876  	args := defaultAttachConfig // narrow copy for initializing non-zero default values
  1877  	if err := unmarshalLaunchAttachArgs(request.Arguments, &args); err != nil {
  1878  		s.sendShowUserErrorResponse(request.Request, FailedToAttach, "Failed to attach", fmt.Sprintf("invalid debug configuration - %v", err))
  1879  		return
  1880  	}
  1881  	s.config.log.Debug("parsed launch config: ", prettyPrint(args))
  1882  
  1883  	switch args.Mode {
  1884  	case "":
  1885  		args.Mode = "local"
  1886  		fallthrough
  1887  	case "local":
  1888  		if s.debugger != nil {
  1889  			s.sendShowUserErrorResponse(
  1890  				request.Request, FailedToAttach,
  1891  				"Failed to attach",
  1892  				fmt.Sprintf("debug session already in progress at %s - use remote mode to connect to a server with an active debug session", s.address()))
  1893  			return
  1894  		}
  1895  		if args.AttachWaitFor != "" && args.ProcessID != 0 {
  1896  			s.sendShowUserErrorResponse(
  1897  				request.Request,
  1898  				FailedToAttach,
  1899  				"Failed to attach",
  1900  				"'processId' and 'waitFor' are mutually exclusive, and can't be specified at the same time")
  1901  			return
  1902  		} else if args.AttachWaitFor != "" {
  1903  			s.config.Debugger.AttachWaitFor = args.AttachWaitFor
  1904  			// Keep the default value the same as waitfor-interval.
  1905  			s.config.Debugger.AttachWaitForInterval = 1
  1906  			s.config.log.Debugf("Waiting for a process with a name beginning with this prefix: %s", args.AttachWaitFor)
  1907  		} else if args.ProcessID != 0 {
  1908  			s.config.Debugger.AttachPid = args.ProcessID
  1909  			s.config.log.Debugf("Attaching to pid %d", args.ProcessID)
  1910  		} else {
  1911  			s.sendShowUserErrorResponse(
  1912  				request.Request,
  1913  				FailedToAttach,
  1914  				"Failed to attach",
  1915  				"The 'processId' or 'waitFor' attribute is missing in debug configuration")
  1916  			return
  1917  		}
  1918  		if args.Backend == "" {
  1919  			args.Backend = "default"
  1920  		}
  1921  		s.config.Debugger.Backend = args.Backend
  1922  		var err error
  1923  		func() {
  1924  			s.mu.Lock()
  1925  			defer s.mu.Unlock() // Make sure to unlock in case of panic that will become internal error
  1926  			s.debugger, err = debugger.New(&s.config.Debugger, nil)
  1927  		}()
  1928  		if err != nil {
  1929  			s.sendShowUserErrorResponse(request.Request, FailedToAttach, "Failed to attach", err.Error())
  1930  			return
  1931  		}
  1932  		// Give the user an option to terminate debuggee when client disconnects (default is to leave it)
  1933  		s.send(&dap.CapabilitiesEvent{Event: *newEvent("capabilities"), Body: dap.CapabilitiesEventBody{Capabilities: dap.Capabilities{SupportTerminateDebuggee: true}}})
  1934  	case "remote":
  1935  		if s.debugger == nil {
  1936  			s.sendShowUserErrorResponse(request.Request, FailedToAttach, "Failed to attach", "no debugger found")
  1937  			return
  1938  		}
  1939  		s.config.log.Debug("debugger already started")
  1940  		// Halt for configuration sequence. onConfigurationDone will restart
  1941  		// execution if user requested !stopOnEntry.
  1942  		s.changeStateMu.Lock()
  1943  		defer s.changeStateMu.Unlock()
  1944  		if _, err := s.halt(); err != nil {
  1945  			s.sendShowUserErrorResponse(request.Request, FailedToAttach, "Failed to attach", err.Error())
  1946  			return
  1947  		}
  1948  		// Enable StepBack controls on supported backends
  1949  		if s.config.Debugger.Backend == "rr" {
  1950  			s.send(&dap.CapabilitiesEvent{Event: *newEvent("capabilities"), Body: dap.CapabilitiesEventBody{Capabilities: dap.Capabilities{SupportsStepBack: true}}})
  1951  		}
  1952  		// Customize termination options for debugger and debuggee
  1953  		if s.config.AcceptMulti {
  1954  			// User can stop debugger with process or leave it running
  1955  			s.send(&dap.CapabilitiesEvent{Event: *newEvent("capabilities"), Body: dap.CapabilitiesEventBody{Capabilities: dap.Capabilities{SupportTerminateDebuggee: true}}})
  1956  			// TODO(polina): support SupportSuspendDebuggee when available
  1957  		} else if s.config.Debugger.AttachPid > 0 {
  1958  			// User can stop debugger with process or leave the process running
  1959  			s.send(&dap.CapabilitiesEvent{Event: *newEvent("capabilities"), Body: dap.CapabilitiesEventBody{Capabilities: dap.Capabilities{SupportTerminateDebuggee: true}}})
  1960  		} // else program was launched and the only option will be to stop both
  1961  	default:
  1962  		s.sendShowUserErrorResponse(request.Request, FailedToAttach, "Failed to attach",
  1963  			fmt.Sprintf("invalid debug configuration - unsupported 'mode' attribute %q", args.Mode))
  1964  		return
  1965  	}
  1966  
  1967  	s.setLaunchAttachArgs(args.LaunchAttachCommonConfig)
  1968  
  1969  	// Notify the client that the debugger is ready to start accepting
  1970  	// configuration requests for setting breakpoints, etc. The client
  1971  	// will end the configuration sequence with 'configurationDone'.
  1972  	s.send(&dap.InitializedEvent{Event: *newEvent("initialized")})
  1973  	s.send(&dap.AttachResponse{Response: *newResponse(request.Request)})
  1974  }
  1975  
  1976  // onNextRequest handles 'next' request.
  1977  // This is a mandatory request to support.
  1978  func (s *Session) onNextRequest(request *dap.NextRequest, allowNextStateChange *syncflag) {
  1979  	s.sendStepResponse(request.Arguments.ThreadId, &dap.NextResponse{Response: *newResponse(request.Request)})
  1980  	s.stepUntilStopAndNotify(api.Next, request.Arguments.ThreadId, request.Arguments.Granularity, allowNextStateChange)
  1981  }
  1982  
  1983  // onStepInRequest handles 'stepIn' request
  1984  // This is a mandatory request to support.
  1985  func (s *Session) onStepInRequest(request *dap.StepInRequest, allowNextStateChange *syncflag) {
  1986  	s.sendStepResponse(request.Arguments.ThreadId, &dap.StepInResponse{Response: *newResponse(request.Request)})
  1987  	s.stepUntilStopAndNotify(api.Step, request.Arguments.ThreadId, request.Arguments.Granularity, allowNextStateChange)
  1988  }
  1989  
  1990  // onStepOutRequest handles 'stepOut' request
  1991  // This is a mandatory request to support.
  1992  func (s *Session) onStepOutRequest(request *dap.StepOutRequest, allowNextStateChange *syncflag) {
  1993  	s.sendStepResponse(request.Arguments.ThreadId, &dap.StepOutResponse{Response: *newResponse(request.Request)})
  1994  	s.stepUntilStopAndNotify(api.StepOut, request.Arguments.ThreadId, request.Arguments.Granularity, allowNextStateChange)
  1995  }
  1996  
  1997  func (s *Session) sendStepResponse(threadId int, message dap.Message) {
  1998  	// All the threads will be continued by this request, so we need to send
  1999  	// a continued event so the UI can properly reflect the current state.
  2000  	s.send(&dap.ContinuedEvent{
  2001  		Event: *newEvent("continued"),
  2002  		Body: dap.ContinuedEventBody{
  2003  			ThreadId:            threadId,
  2004  			AllThreadsContinued: true,
  2005  		},
  2006  	})
  2007  	s.send(message)
  2008  }
  2009  
  2010  func stoppedGoroutineID(state *api.DebuggerState) (id int64) {
  2011  	if state.SelectedGoroutine != nil {
  2012  		id = state.SelectedGoroutine.ID
  2013  	} else if state.CurrentThread != nil {
  2014  		id = state.CurrentThread.GoroutineID
  2015  	}
  2016  	return id
  2017  }
  2018  
  2019  // stoppedOnBreakpointGoroutineID gets the goroutine id of the first goroutine
  2020  // that is stopped on a real breakpoint, starting with the selected goroutine.
  2021  func (s *Session) stoppedOnBreakpointGoroutineID(state *api.DebuggerState) (int64, *api.Breakpoint) {
  2022  	// Use the first goroutine that is stopped on a breakpoint.
  2023  	gs := s.stoppedGs(state)
  2024  	if len(gs) == 0 {
  2025  		return 0, nil
  2026  	}
  2027  	goid := gs[0]
  2028  	if goid == 0 {
  2029  		return goid, state.CurrentThread.Breakpoint
  2030  	}
  2031  	g, _ := s.debugger.FindGoroutine(goid)
  2032  	if g == nil || g.Thread == nil {
  2033  		return goid, nil
  2034  	}
  2035  	bp := g.Thread.Breakpoint()
  2036  	if bp == nil || bp.Breakpoint == nil || bp.Breakpoint.Logical == nil {
  2037  		return goid, nil
  2038  	}
  2039  	abp := api.ConvertLogicalBreakpoint(bp.Breakpoint.Logical)
  2040  	api.ConvertPhysicalBreakpoints(abp, bp.Breakpoint.Logical, []int{0}, []*proc.Breakpoint{bp.Breakpoint})
  2041  	return goid, abp
  2042  }
  2043  
  2044  // stepUntilStopAndNotify is a wrapper around runUntilStopAndNotify that
  2045  // first switches selected goroutine. allowNextStateChange is
  2046  // a channel that will be closed to signal that an
  2047  // asynchronous command has completed setup or was interrupted
  2048  // due to an error, so the server is ready to receive new requests.
  2049  func (s *Session) stepUntilStopAndNotify(command string, threadId int, granularity dap.SteppingGranularity, allowNextStateChange *syncflag) {
  2050  	defer allowNextStateChange.raise()
  2051  	_, err := s.debugger.Command(&api.DebuggerCommand{Name: api.SwitchGoroutine, GoroutineID: int64(threadId)}, nil)
  2052  	if err != nil {
  2053  		s.config.log.Errorf("Error switching goroutines while stepping: %v", err)
  2054  		// If we encounter an error, we will have to send a stopped event
  2055  		// since we already sent the step response.
  2056  		stopped := &dap.StoppedEvent{Event: *newEvent("stopped")}
  2057  		stopped.Body.AllThreadsStopped = true
  2058  		if state, err := s.debugger.State(false); err != nil {
  2059  			s.config.log.Errorf("Error retrieving state: %e", err)
  2060  		} else {
  2061  			stopped.Body.ThreadId = int(stoppedGoroutineID(state))
  2062  		}
  2063  		stopped.Body.Reason = "error"
  2064  		stopped.Body.Text = err.Error()
  2065  		s.send(stopped)
  2066  		return
  2067  	}
  2068  
  2069  	if granularity == "instruction" {
  2070  		switch command {
  2071  		case api.ReverseNext:
  2072  			command = api.ReverseStepInstruction
  2073  		default:
  2074  			// TODO(suzmue): consider differentiating between next, step in, and step out.
  2075  			// For example, next could step over call requests.
  2076  			command = api.StepInstruction
  2077  		}
  2078  	}
  2079  	s.runUntilStopAndNotify(command, allowNextStateChange)
  2080  }
  2081  
  2082  // onPauseRequest handles 'pause' request.
  2083  // This is a mandatory request to support.
  2084  func (s *Session) onPauseRequest(request *dap.PauseRequest) {
  2085  	s.changeStateMu.Lock()
  2086  	defer s.changeStateMu.Unlock()
  2087  	s.setHaltRequested(true)
  2088  	_, err := s.halt()
  2089  	if err != nil {
  2090  		s.sendErrorResponse(request.Request, UnableToHalt, "Unable to halt execution", err.Error())
  2091  		return
  2092  	}
  2093  	s.send(&dap.PauseResponse{Response: *newResponse(request.Request)})
  2094  	// No need to send any event here.
  2095  	// If we received this request while stopped, there already was an event for the stop.
  2096  	// If we received this while running, then doCommand will unblock and trigger the right
  2097  	// event, using debugger.StopReason because manual stop reason always wins even if we
  2098  	// simultaneously receive a manual stop request and hit a breakpoint.
  2099  }
  2100  
  2101  // stackFrame represents the index of a frame within
  2102  // the context of a stack of a specific goroutine.
  2103  type stackFrame struct {
  2104  	goroutineID int
  2105  	frameIndex  int
  2106  }
  2107  
  2108  // onStackTraceRequest handles 'stackTrace' requests.
  2109  // This is a mandatory request to support.
  2110  // As per DAP spec, this request only gets triggered as a follow-up
  2111  // to a successful threads request as part of the "request waterfall".
  2112  func (s *Session) onStackTraceRequest(request *dap.StackTraceRequest) {
  2113  	if s.debugger == nil {
  2114  		s.sendErrorResponse(request.Request, UnableToProduceStackTrace, "Unable to produce stack trace", "debugger is nil")
  2115  		return
  2116  	}
  2117  
  2118  	goroutineID := request.Arguments.ThreadId
  2119  	start := request.Arguments.StartFrame
  2120  	if start < 0 {
  2121  		start = 0
  2122  	}
  2123  	levels := s.args.StackTraceDepth
  2124  	if request.Arguments.Levels > 0 {
  2125  		levels = request.Arguments.Levels
  2126  	}
  2127  
  2128  	// Since the backend doesn't support paging, we load all frames up to
  2129  	// the requested depth and then slice them here per
  2130  	// `supportsDelayedStackTraceLoading` capability.
  2131  	frames, err := s.debugger.Stacktrace(int64(goroutineID), start+levels-1, 0)
  2132  	if err != nil {
  2133  		s.sendErrorResponse(request.Request, UnableToProduceStackTrace, "Unable to produce stack trace", err.Error())
  2134  		return
  2135  	}
  2136  
  2137  	// Determine if the goroutine is a system goroutine.
  2138  	isSystemGoroutine := true
  2139  	if g, _ := s.debugger.FindGoroutine(int64(goroutineID)); g != nil {
  2140  		isSystemGoroutine = g.System(s.debugger.Target())
  2141  	}
  2142  
  2143  	stackFrames := []dap.StackFrame{} // initialize to empty, since nil is not an accepted response.
  2144  	for i := 0; i < levels && i+start < len(frames); i++ {
  2145  		frame := frames[start+i]
  2146  		loc := &frame.Call
  2147  		uniqueStackFrameID := s.stackFrameHandles.create(stackFrame{goroutineID, start + i})
  2148  		stackFrame := dap.StackFrame{Id: uniqueStackFrameID, Line: loc.Line, Name: fnName(loc), InstructionPointerReference: fmt.Sprintf("%#x", loc.PC)}
  2149  		if loc.File != "<autogenerated>" {
  2150  			clientPath := s.toClientPath(loc.File)
  2151  			stackFrame.Source = &dap.Source{Name: filepath.Base(clientPath), Path: clientPath}
  2152  		}
  2153  		stackFrame.Column = 0
  2154  
  2155  		packageName := fnPackageName(loc)
  2156  		if !isSystemGoroutine && packageName == "runtime" {
  2157  			stackFrame.PresentationHint = "subtle"
  2158  		}
  2159  		stackFrames = append(stackFrames, stackFrame)
  2160  	}
  2161  
  2162  	totalFrames := len(frames)
  2163  	if len(frames) >= start+levels && !frames[len(frames)-1].Bottom {
  2164  		// We don't know the exact number of available stack frames, so
  2165  		// add an arbitrary number so the client knows to request additional
  2166  		// frames.
  2167  		totalFrames += s.args.StackTraceDepth
  2168  	}
  2169  	response := &dap.StackTraceResponse{
  2170  		Response: *newResponse(request.Request),
  2171  		Body:     dap.StackTraceResponseBody{StackFrames: stackFrames, TotalFrames: totalFrames},
  2172  	}
  2173  	s.send(response)
  2174  }
  2175  
  2176  // onScopesRequest handles 'scopes' requests.
  2177  // This is a mandatory request to support.
  2178  // It is automatically sent as part of the threads > stacktrace > scopes > variables
  2179  // "waterfall" to highlight the topmost frame at stops, after an evaluate request
  2180  // for the selected scope or when a user selects different scopes in the UI.
  2181  func (s *Session) onScopesRequest(request *dap.ScopesRequest) {
  2182  	sf, ok := s.stackFrameHandles.get(request.Arguments.FrameId)
  2183  	if !ok {
  2184  		s.sendErrorResponse(request.Request, UnableToListLocals, "Unable to list locals", fmt.Sprintf("unknown frame id %d", request.Arguments.FrameId))
  2185  		return
  2186  	}
  2187  
  2188  	goid := sf.(stackFrame).goroutineID
  2189  	frame := sf.(stackFrame).frameIndex
  2190  
  2191  	// Check if the function is optimized.
  2192  	fn, err := s.debugger.Function(int64(goid), frame, 0)
  2193  	if fn == nil || err != nil {
  2194  		var details string
  2195  		if err != nil {
  2196  			details = err.Error()
  2197  		}
  2198  		s.sendErrorResponse(request.Request, UnableToListArgs, "Unable to find enclosing function", details)
  2199  		return
  2200  	}
  2201  	suffix := ""
  2202  	if fn.Optimized() {
  2203  		suffix = " (warning: optimized function)"
  2204  	}
  2205  	// Retrieve arguments
  2206  	args, err := s.debugger.FunctionArguments(int64(goid), frame, 0, DefaultLoadConfig)
  2207  	if err != nil {
  2208  		s.sendErrorResponse(request.Request, UnableToListArgs, "Unable to list args", err.Error())
  2209  		return
  2210  	}
  2211  
  2212  	// Retrieve local variables
  2213  	locals, err := s.debugger.LocalVariables(int64(goid), frame, 0, DefaultLoadConfig)
  2214  	if err != nil {
  2215  		s.sendErrorResponse(request.Request, UnableToListLocals, "Unable to list locals", err.Error())
  2216  		return
  2217  	}
  2218  	locScope := &fullyQualifiedVariable{&proc.Variable{Name: fmt.Sprintf("Locals%s", suffix), Children: slicePtrVarToSliceVar(append(args, locals...))}, "", true, 0}
  2219  	scopeLocals := dap.Scope{Name: locScope.Name, VariablesReference: s.variableHandles.create(locScope)}
  2220  	scopes := []dap.Scope{scopeLocals}
  2221  
  2222  	if s.args.ShowGlobalVariables {
  2223  		// Limit what global variables we will return to the current package only.
  2224  		// TODO(polina): This is how vscode-go currently does it to make
  2225  		// the amount of the returned data manageable. In fact, this is
  2226  		// considered so expensive even with the package filter, that
  2227  		// the default for showGlobalVariables was recently flipped to
  2228  		// not showing. If we delay loading of the globals until the corresponding
  2229  		// scope is expanded, generating an explicit variable request,
  2230  		// should we consider making all globals accessible with a scope per package?
  2231  		// Or users can just rely on watch variables.
  2232  		currPkg, err := s.debugger.CurrentPackage()
  2233  		if err != nil {
  2234  			s.sendErrorResponse(request.Request, UnableToListGlobals, "Unable to list globals", err.Error())
  2235  			return
  2236  		}
  2237  		currPkgFilter := fmt.Sprintf("^%s\\.", currPkg)
  2238  		globals, err := s.debugger.PackageVariables(currPkgFilter, DefaultLoadConfig)
  2239  		if err != nil {
  2240  			s.sendErrorResponse(request.Request, UnableToListGlobals, "Unable to list globals", err.Error())
  2241  			return
  2242  		}
  2243  		// Remove package prefix from the fully-qualified variable names.
  2244  		// We will include the package info once in the name of the scope instead.
  2245  		for i, g := range globals {
  2246  			globals[i].Name = strings.TrimPrefix(g.Name, currPkg+".")
  2247  		}
  2248  
  2249  		globScope := &fullyQualifiedVariable{&proc.Variable{
  2250  			Name:     fmt.Sprintf("Globals (package %s)", currPkg),
  2251  			Children: slicePtrVarToSliceVar(globals),
  2252  		}, currPkg, true, 0}
  2253  		scopeGlobals := dap.Scope{Name: globScope.Name, VariablesReference: s.variableHandles.create(globScope)}
  2254  		scopes = append(scopes, scopeGlobals)
  2255  	}
  2256  
  2257  	if s.args.ShowRegisters {
  2258  		// Retrieve registers
  2259  		regs, err := s.debugger.ScopeRegisters(int64(goid), frame, 0)
  2260  		if err != nil {
  2261  			s.sendErrorResponse(request.Request, UnableToListRegisters, "Unable to list registers", err.Error())
  2262  			return
  2263  		}
  2264  		outRegs := api.ConvertRegisters(regs, s.debugger.DwarfRegisterToString, false)
  2265  		regsVar := make([]proc.Variable, len(outRegs))
  2266  		for i, r := range outRegs {
  2267  			regsVar[i] = proc.Variable{
  2268  				Name:  r.Name,
  2269  				Value: constant.MakeString(r.Value),
  2270  				Kind:  reflect.Kind(proc.VariableConstant),
  2271  			}
  2272  		}
  2273  		regsScope := &fullyQualifiedVariable{&proc.Variable{Name: "Registers", Children: regsVar}, "", true, 0}
  2274  		scopeRegisters := dap.Scope{Name: regsScope.Name, VariablesReference: s.variableHandles.create(regsScope)}
  2275  		scopes = append(scopes, scopeRegisters)
  2276  	}
  2277  	response := &dap.ScopesResponse{
  2278  		Response: *newResponse(request.Request),
  2279  		Body:     dap.ScopesResponseBody{Scopes: scopes},
  2280  	}
  2281  	s.send(response)
  2282  }
  2283  
  2284  func slicePtrVarToSliceVar(vars []*proc.Variable) []proc.Variable {
  2285  	r := make([]proc.Variable, len(vars))
  2286  	for i := range vars {
  2287  		r[i] = *vars[i]
  2288  	}
  2289  	return r
  2290  }
  2291  
  2292  // onVariablesRequest handles 'variables' requests.
  2293  // This is a mandatory request to support.
  2294  func (s *Session) onVariablesRequest(request *dap.VariablesRequest) {
  2295  	ref := request.Arguments.VariablesReference
  2296  	v, ok := s.variableHandles.get(ref)
  2297  	if !ok {
  2298  		s.sendErrorResponse(request.Request, UnableToLookupVariable, "Unable to lookup variable", fmt.Sprintf("unknown reference %d", ref))
  2299  		return
  2300  	}
  2301  
  2302  	// If there is a filter applied, we will need to create a new variable that includes
  2303  	// the values actually needed to load. This cannot be done when loading the parent
  2304  	// node, since it is unknown at that point which children will need to be loaded.
  2305  	if request.Arguments.Filter == "indexed" {
  2306  		var err error
  2307  		v, err = s.maybeLoadResliced(v, request.Arguments.Start, request.Arguments.Count)
  2308  		if err != nil {
  2309  			s.sendErrorResponse(request.Request, UnableToLookupVariable, "Unable to lookup variable", err.Error())
  2310  			return
  2311  		}
  2312  	}
  2313  
  2314  	children := []dap.Variable{} // must return empty array, not null, if no children
  2315  	if request.Arguments.Filter == "named" || request.Arguments.Filter == "" {
  2316  		named, err := s.metadataToDAPVariables(v)
  2317  		if err != nil {
  2318  			s.sendErrorResponse(request.Request, UnableToLookupVariable, "Unable to lookup variable", err.Error())
  2319  			return
  2320  		}
  2321  		children = append(children, named...)
  2322  	}
  2323  	if request.Arguments.Filter == "indexed" || request.Arguments.Filter == "" {
  2324  		indexed := s.childrenToDAPVariables(v)
  2325  		children = append(children, indexed...)
  2326  	}
  2327  	response := &dap.VariablesResponse{
  2328  		Response: *newResponse(request.Request),
  2329  		Body:     dap.VariablesResponseBody{Variables: children},
  2330  	}
  2331  	s.send(response)
  2332  }
  2333  
  2334  func (s *Session) maybeLoadResliced(v *fullyQualifiedVariable, start, count int) (*fullyQualifiedVariable, error) {
  2335  	if start == 0 {
  2336  		want := count
  2337  		if v.Kind == reflect.Map {
  2338  			// For maps, we need to have 2*count children since each key-value pair is two variables.
  2339  			want *= 2
  2340  		}
  2341  		if want == len(v.Children) {
  2342  			// If we have already loaded the correct children,
  2343  			// just return the variable.
  2344  			return v, nil
  2345  		}
  2346  	}
  2347  	indexedLoadConfig := DefaultLoadConfig
  2348  	indexedLoadConfig.MaxArrayValues = count
  2349  	newV, err := s.debugger.LoadResliced(v.Variable, start, indexedLoadConfig)
  2350  	if err != nil {
  2351  		return nil, err
  2352  	}
  2353  	return &fullyQualifiedVariable{newV, v.fullyQualifiedNameOrExpr, false, start}, nil
  2354  }
  2355  
  2356  // getIndexedVariableCount returns the number of indexed variables
  2357  // for a DAP variable. For maps this may be less than the actual
  2358  // number of children returned, since a key-value pair may be split
  2359  // into two separate children.
  2360  func getIndexedVariableCount(v *proc.Variable) int {
  2361  	indexedVars := 0
  2362  	switch v.Kind {
  2363  	case reflect.Array, reflect.Slice, reflect.Map:
  2364  		indexedVars = int(v.Len)
  2365  	}
  2366  	return indexedVars
  2367  }
  2368  
  2369  // childrenToDAPVariables returns the DAP presentation of the referenced variable's children.
  2370  func (s *Session) childrenToDAPVariables(v *fullyQualifiedVariable) []dap.Variable {
  2371  	// TODO(polina): consider convertVariableToString instead of convertVariable
  2372  	// and avoid unnecessary creation of variable handles when this is called to
  2373  	// compute evaluate names when this is called from onSetVariableRequest.
  2374  	children := []dap.Variable{} // must return empty array, not null, if no children
  2375  
  2376  	switch v.Kind {
  2377  	case reflect.Map:
  2378  		for i := 0; i < len(v.Children); i += 2 {
  2379  			// A map will have twice as many children as there are key-value elements.
  2380  			kvIndex := i / 2
  2381  			// Process children in pairs: even indices are map keys, odd indices are values.
  2382  			keyv, valv := &v.Children[i], &v.Children[i+1]
  2383  			keyexpr := fmt.Sprintf("(*(*%q)(%#x))", keyv.TypeString(), keyv.Addr)
  2384  			valexpr := fmt.Sprintf("%s[%s]", v.fullyQualifiedNameOrExpr, keyexpr)
  2385  			switch keyv.Kind {
  2386  			// For value expression, use the key value, not the corresponding expression if the key is a scalar.
  2387  			case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128,
  2388  				reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
  2389  				reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  2390  				valexpr = fmt.Sprintf("%s[%s]", v.fullyQualifiedNameOrExpr, api.VariableValueAsString(keyv))
  2391  			case reflect.String:
  2392  				if key := constant.StringVal(keyv.Value); keyv.Len == int64(len(key)) { // fully loaded
  2393  					valexpr = fmt.Sprintf("%s[%q]", v.fullyQualifiedNameOrExpr, key)
  2394  				}
  2395  			}
  2396  			key, keyref := s.convertVariable(keyv, keyexpr)
  2397  			val, valref := s.convertVariable(valv, valexpr)
  2398  			keyType := s.getTypeIfSupported(keyv)
  2399  			valType := s.getTypeIfSupported(valv)
  2400  			// If key or value or both are scalars, we can use
  2401  			// a single variable to represent key:value format.
  2402  			// Otherwise, we must return separate variables for both.
  2403  			if keyref > 0 && valref > 0 { // Both are not scalars
  2404  				keyvar := dap.Variable{
  2405  					Name:               fmt.Sprintf("[key %d]", v.startIndex+kvIndex),
  2406  					EvaluateName:       keyexpr,
  2407  					Type:               keyType,
  2408  					Value:              key,
  2409  					VariablesReference: keyref,
  2410  					IndexedVariables:   getIndexedVariableCount(keyv),
  2411  					NamedVariables:     getNamedVariableCount(keyv),
  2412  				}
  2413  				valvar := dap.Variable{
  2414  					Name:               fmt.Sprintf("[val %d]", v.startIndex+kvIndex),
  2415  					EvaluateName:       valexpr,
  2416  					Type:               valType,
  2417  					Value:              val,
  2418  					VariablesReference: valref,
  2419  					IndexedVariables:   getIndexedVariableCount(valv),
  2420  					NamedVariables:     getNamedVariableCount(valv),
  2421  				}
  2422  				children = append(children, keyvar, valvar)
  2423  			} else { // At least one is a scalar
  2424  				keyValType := valType
  2425  				if len(keyType) > 0 && len(valType) > 0 {
  2426  					keyValType = fmt.Sprintf("%s: %s", keyType, valType)
  2427  				}
  2428  				kvvar := dap.Variable{
  2429  					Name:         key,
  2430  					EvaluateName: valexpr,
  2431  					Type:         keyValType,
  2432  					Value:        val,
  2433  				}
  2434  				if keyref != 0 { // key is a type to be expanded
  2435  					if len(key) > maxMapKeyValueLen {
  2436  						// Truncate and make unique
  2437  						kvvar.Name = fmt.Sprintf("%s... @ %#x", key[0:maxMapKeyValueLen], keyv.Addr)
  2438  					}
  2439  					kvvar.VariablesReference = keyref
  2440  					kvvar.IndexedVariables = getIndexedVariableCount(keyv)
  2441  					kvvar.NamedVariables = getNamedVariableCount(keyv)
  2442  				} else if valref != 0 { // val is a type to be expanded
  2443  					kvvar.VariablesReference = valref
  2444  					kvvar.IndexedVariables = getIndexedVariableCount(valv)
  2445  					kvvar.NamedVariables = getNamedVariableCount(valv)
  2446  				}
  2447  				children = append(children, kvvar)
  2448  			}
  2449  		}
  2450  	case reflect.Slice, reflect.Array:
  2451  		children = make([]dap.Variable, len(v.Children))
  2452  		for i := range v.Children {
  2453  			idx := v.startIndex + i
  2454  			cfqname := fmt.Sprintf("%s[%d]", v.fullyQualifiedNameOrExpr, idx)
  2455  			cvalue, cvarref := s.convertVariable(&v.Children[i], cfqname)
  2456  			children[i] = dap.Variable{
  2457  				Name:               fmt.Sprintf("[%d]", idx),
  2458  				EvaluateName:       cfqname,
  2459  				Type:               s.getTypeIfSupported(&v.Children[i]),
  2460  				Value:              cvalue,
  2461  				VariablesReference: cvarref,
  2462  				IndexedVariables:   getIndexedVariableCount(&v.Children[i]),
  2463  				NamedVariables:     getNamedVariableCount(&v.Children[i]),
  2464  			}
  2465  		}
  2466  	default:
  2467  		children = make([]dap.Variable, len(v.Children))
  2468  		for i := range v.Children {
  2469  			c := &v.Children[i]
  2470  			cfqname := fmt.Sprintf("%s.%s", v.fullyQualifiedNameOrExpr, c.Name)
  2471  
  2472  			switch {
  2473  			case strings.HasPrefix(c.Name, "~") || strings.HasPrefix(c.Name, "."):
  2474  				cfqname = ""
  2475  			case v.isScope && v.fullyQualifiedNameOrExpr == "":
  2476  				cfqname = c.Name
  2477  			case v.fullyQualifiedNameOrExpr == "":
  2478  				cfqname = ""
  2479  			case v.Kind == reflect.Interface:
  2480  				cfqname = fmt.Sprintf("%s.(%s)", v.fullyQualifiedNameOrExpr, c.Name) // c is data
  2481  			case v.Kind == reflect.Ptr:
  2482  				cfqname = fmt.Sprintf("(*%v)", v.fullyQualifiedNameOrExpr) // c is the nameless pointer value
  2483  			case v.Kind == reflect.Complex64 || v.Kind == reflect.Complex128:
  2484  				cfqname = "" // complex children are not struct fields and can't be accessed directly
  2485  			}
  2486  			cvalue, cvarref := s.convertVariable(c, cfqname)
  2487  
  2488  			// Annotate any shadowed variables to "(name)" in order
  2489  			// to distinguish from non-shadowed variables.
  2490  			// TODO(suzmue): should we support a special evaluateName syntax that
  2491  			// can access shadowed variables?
  2492  			name := c.Name
  2493  			if c.Flags&proc.VariableShadowed == proc.VariableShadowed {
  2494  				name = fmt.Sprintf("(%s)", name)
  2495  			}
  2496  
  2497  			if v.isScope && v.Name == "Registers" {
  2498  				// Align all the register names.
  2499  				name = fmt.Sprintf("%6s", strings.ToLower(c.Name))
  2500  				// Set the correct evaluate name for the register.
  2501  				cfqname = fmt.Sprintf("_%s", strings.ToUpper(c.Name))
  2502  				// Unquote the value
  2503  				if ucvalue, err := strconv.Unquote(cvalue); err == nil {
  2504  					cvalue = ucvalue
  2505  				}
  2506  			}
  2507  
  2508  			children[i] = dap.Variable{
  2509  				Name:               name,
  2510  				EvaluateName:       cfqname,
  2511  				Type:               s.getTypeIfSupported(c),
  2512  				Value:              cvalue,
  2513  				VariablesReference: cvarref,
  2514  				IndexedVariables:   getIndexedVariableCount(c),
  2515  				NamedVariables:     getNamedVariableCount(c),
  2516  			}
  2517  		}
  2518  	}
  2519  	return children
  2520  }
  2521  
  2522  func getNamedVariableCount(v *proc.Variable) int {
  2523  	namedVars := 0
  2524  	if v.Kind == reflect.Map && v.Len > 0 {
  2525  		// len
  2526  		namedVars += 1
  2527  	}
  2528  	if isListOfBytesOrRunes(v) {
  2529  		// string value of array/slice of bytes and runes.
  2530  		namedVars += 1
  2531  	}
  2532  
  2533  	return namedVars
  2534  }
  2535  
  2536  // metadataToDAPVariables returns the DAP presentation of the referenced variable's metadata.
  2537  // These are included as named variables
  2538  func (s *Session) metadataToDAPVariables(v *fullyQualifiedVariable) ([]dap.Variable, error) {
  2539  	children := []dap.Variable{} // must return empty array, not null, if no children
  2540  
  2541  	if v.Kind == reflect.Map && v.Len > 0 {
  2542  		children = append(children, dap.Variable{
  2543  			Name:         "len()",
  2544  			Value:        fmt.Sprintf("%d", v.Len),
  2545  			Type:         "int",
  2546  			EvaluateName: fmt.Sprintf("len(%s)", v.fullyQualifiedNameOrExpr),
  2547  		})
  2548  	}
  2549  
  2550  	if isListOfBytesOrRunes(v.Variable) {
  2551  		// Return the string value of []byte or []rune.
  2552  		typeName := api.PrettyTypeName(v.DwarfType)
  2553  		loadExpr := fmt.Sprintf("string(*(*%q)(%#x))", typeName, v.Addr)
  2554  
  2555  		s.config.log.Debugf("loading %s (type %s) with %s", v.fullyQualifiedNameOrExpr, typeName, loadExpr)
  2556  		// We know that this is an array/slice of Uint8 or Int32, so we will load up to MaxStringLen.
  2557  		config := DefaultLoadConfig
  2558  		config.MaxArrayValues = config.MaxStringLen
  2559  		vLoaded, err := s.debugger.EvalVariableInScope(-1, 0, 0, loadExpr, config)
  2560  		if err == nil {
  2561  			val := s.convertVariableToString(vLoaded)
  2562  			// TODO(suzmue): Add evaluate name. Using string(name) will not get the same result because the
  2563  			// MaxArrayValues is not auto adjusted in evaluate requests like MaxStringLen is adjusted.
  2564  			children = append(children, dap.Variable{
  2565  				Name:  "string()",
  2566  				Value: val,
  2567  				Type:  "string",
  2568  			})
  2569  		} else {
  2570  			s.config.log.Debugf("failed to load %q: %v", v.fullyQualifiedNameOrExpr, err)
  2571  		}
  2572  	}
  2573  	return children, nil
  2574  }
  2575  
  2576  func isListOfBytesOrRunes(v *proc.Variable) bool {
  2577  	if len(v.Children) > 0 && (v.Kind == reflect.Array || v.Kind == reflect.Slice) {
  2578  		childKind := v.Children[0].RealType.Common().ReflectKind
  2579  		return childKind == reflect.Uint8 || childKind == reflect.Int32
  2580  	}
  2581  	return false
  2582  }
  2583  
  2584  func (s *Session) getTypeIfSupported(v *proc.Variable) string {
  2585  	if !s.clientCapabilities.supportsVariableType {
  2586  		return ""
  2587  	}
  2588  	switch v.Kind {
  2589  	case reflect.Interface:
  2590  		if len(v.Children) > 0 {
  2591  			vapi := api.ConvertVar(v)
  2592  			if vapi.Children[0].Kind != reflect.Invalid {
  2593  				return fmt.Sprintf("%s(%s)", vapi.Type, vapi.Children[0].Type)
  2594  			}
  2595  		}
  2596  	}
  2597  	return v.TypeString()
  2598  }
  2599  
  2600  // convertVariable converts proc.Variable to dap.Variable value and reference
  2601  // while keeping track of the full qualified name or load expression.
  2602  // Variable reference is used to keep track of the children associated with each
  2603  // variable. It is shared with the host via scopes or evaluate response and is an index
  2604  // into the s.variableHandles map, used to look up variables and their children on
  2605  // subsequent variables requests. A positive reference signals the host that another
  2606  // variables request can be issued to get the elements of the compound variable. As a
  2607  // custom, a zero reference, reminiscent of a zero pointer, is used to indicate that
  2608  // a scalar variable cannot be "dereferenced" to get its elements (as there are none).
  2609  func (s *Session) convertVariable(v *proc.Variable, qualifiedNameOrExpr string) (value string, variablesReference int) {
  2610  	return s.convertVariableWithOpts(v, qualifiedNameOrExpr, 0)
  2611  }
  2612  
  2613  func (s *Session) convertVariableToString(v *proc.Variable) string {
  2614  	val, _ := s.convertVariableWithOpts(v, "", skipRef)
  2615  	return val
  2616  }
  2617  
  2618  const (
  2619  	// Limit the length of a string representation of a compound or reference type variable.
  2620  	maxVarValueLen = 1 << 8 // 256
  2621  	// Limit the length of an inlined map key.
  2622  	maxMapKeyValueLen = 64
  2623  )
  2624  
  2625  // Flags for convertVariableWithOpts option.
  2626  type convertVariableFlags uint8
  2627  
  2628  const (
  2629  	skipRef convertVariableFlags = 1 << iota
  2630  	showFullValue
  2631  )
  2632  
  2633  // convertVariableWithOpts allows to skip reference generation in case all we need is
  2634  // a string representation of the variable. When the variable is a compound or reference
  2635  // type variable and its full string representation can be larger than defaultMaxValueLen,
  2636  // this returns a truncated value unless showFull option flag is set.
  2637  func (s *Session) convertVariableWithOpts(v *proc.Variable, qualifiedNameOrExpr string, opts convertVariableFlags) (value string, variablesReference int) {
  2638  	canHaveRef := false
  2639  	maybeCreateVariableHandle := func(v *proc.Variable) int {
  2640  		canHaveRef = true
  2641  		if opts&skipRef != 0 {
  2642  			return 0
  2643  		}
  2644  		return s.variableHandles.create(&fullyQualifiedVariable{v, qualifiedNameOrExpr, false /*not a scope*/, 0})
  2645  	}
  2646  	value = api.ConvertVar(v).SinglelineStringWithShortTypes()
  2647  	if v.Unreadable != nil {
  2648  		return value, 0
  2649  	}
  2650  
  2651  	// Some of the types might be fully or partially not loaded based on LoadConfig.
  2652  	// Those that are fully missing (e.g. due to hitting MaxVariableRecurse), can be reloaded in place.
  2653  	reloadVariable := func(v *proc.Variable, qualifiedNameOrExpr string) (value string) {
  2654  		// We might be loading variables from the frame that's not topmost, so use
  2655  		// frame-independent address-based expression, not fully-qualified name as per
  2656  		// https://gitlab.com/Raven-IO/raven-delve/blob/master/Documentation/api/ClientHowto.md#looking-into-variables.
  2657  		// TODO(polina): Get *proc.Variable object from debugger instead. Export a function to set v.loaded to false
  2658  		// and call v.loadValue gain with a different load config. It's more efficient, and it's guaranteed to keep
  2659  		// working with generics.
  2660  		value = api.ConvertVar(v).SinglelineStringWithShortTypes()
  2661  		typeName := api.PrettyTypeName(v.DwarfType)
  2662  		loadExpr := fmt.Sprintf("*(*%q)(%#x)", typeName, v.Addr)
  2663  		s.config.log.Debugf("loading %s (type %s) with %s", qualifiedNameOrExpr, typeName, loadExpr)
  2664  		// Make sure we can load the pointers directly, not by updating just the child
  2665  		// This is not really necessary now because users have no way of setting FollowPointers to false.
  2666  		config := DefaultLoadConfig
  2667  		config.FollowPointers = true
  2668  		vLoaded, err := s.debugger.EvalVariableInScope(-1, 0, 0, loadExpr, config)
  2669  		if err != nil {
  2670  			value += fmt.Sprintf(" - FAILED TO LOAD: %s", err)
  2671  		} else {
  2672  			v.Children = vLoaded.Children
  2673  			v.Value = vLoaded.Value
  2674  			value = api.ConvertVar(v).SinglelineStringWithShortTypes()
  2675  		}
  2676  		return value
  2677  	}
  2678  
  2679  	switch v.Kind {
  2680  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  2681  		n, _ := strconv.ParseUint(api.ExtractIntValue(api.ConvertVar(v).Value), 10, 64)
  2682  		value = fmt.Sprintf("%s = %#x", value, n)
  2683  	case reflect.UnsafePointer:
  2684  		// Skip child reference
  2685  	case reflect.Ptr:
  2686  		if v.DwarfType != nil && len(v.Children) > 0 && v.Children[0].Addr != 0 && v.Children[0].Kind != reflect.Invalid {
  2687  			if v.Children[0].OnlyAddr { // Not loaded
  2688  				if v.Addr == 0 {
  2689  					// This is equivalent to the following with the cli:
  2690  					//    (dlv) p &a7
  2691  					//    (**main.FooBar)(0xc0000a3918)
  2692  					//
  2693  					// TODO(polina): what is more appropriate?
  2694  					// Option 1: leave it unloaded because it is a special case
  2695  					// Option 2: load it, but then we have to load the child, not the parent, unlike all others
  2696  					// TODO(polina): see if reloadVariable can be reused here
  2697  					cTypeName := api.PrettyTypeName(v.Children[0].DwarfType)
  2698  					cLoadExpr := fmt.Sprintf("*(*%q)(%#x)", cTypeName, v.Children[0].Addr)
  2699  					s.config.log.Debugf("loading *(%s) (type %s) with %s", qualifiedNameOrExpr, cTypeName, cLoadExpr)
  2700  					cLoaded, err := s.debugger.EvalVariableInScope(-1, 0, 0, cLoadExpr, DefaultLoadConfig)
  2701  					if err != nil {
  2702  						value += fmt.Sprintf(" - FAILED TO LOAD: %s", err)
  2703  					} else {
  2704  						cLoaded.Name = v.Children[0].Name // otherwise, this will be the pointer expression
  2705  						v.Children = []proc.Variable{*cLoaded}
  2706  						value = api.ConvertVar(v).SinglelineStringWithShortTypes()
  2707  					}
  2708  				} else {
  2709  					value = reloadVariable(v, qualifiedNameOrExpr)
  2710  				}
  2711  			}
  2712  			if !v.Children[0].OnlyAddr {
  2713  				variablesReference = maybeCreateVariableHandle(v)
  2714  			}
  2715  		}
  2716  	case reflect.Slice, reflect.Array:
  2717  		if v.Len > int64(len(v.Children)) { // Not fully loaded
  2718  			if v.Base != 0 && len(v.Children) == 0 { // Fully missing
  2719  				value = reloadVariable(v, qualifiedNameOrExpr)
  2720  			} else if !s.clientCapabilities.supportsVariablePaging {
  2721  				value = fmt.Sprintf("(loaded %d/%d) ", len(v.Children), v.Len) + value
  2722  			}
  2723  		}
  2724  		if v.Base != 0 && len(v.Children) > 0 {
  2725  			variablesReference = maybeCreateVariableHandle(v)
  2726  		}
  2727  	case reflect.Map:
  2728  		if v.Len > int64(len(v.Children)/2) { // Not fully loaded
  2729  			if len(v.Children) == 0 { // Fully missing
  2730  				value = reloadVariable(v, qualifiedNameOrExpr)
  2731  			} else if !s.clientCapabilities.supportsVariablePaging {
  2732  				value = fmt.Sprintf("(loaded %d/%d) ", len(v.Children)/2, v.Len) + value
  2733  			}
  2734  		}
  2735  		if v.Base != 0 && len(v.Children) > 0 {
  2736  			variablesReference = maybeCreateVariableHandle(v)
  2737  		}
  2738  	case reflect.String:
  2739  		// TODO(polina): implement auto-loading here.
  2740  	case reflect.Interface:
  2741  		if v.Addr != 0 && len(v.Children) > 0 && v.Children[0].Kind != reflect.Invalid && v.Children[0].Addr != 0 {
  2742  			if v.Children[0].OnlyAddr { // Not loaded
  2743  				value = reloadVariable(v, qualifiedNameOrExpr)
  2744  			}
  2745  			if !v.Children[0].OnlyAddr {
  2746  				variablesReference = maybeCreateVariableHandle(v)
  2747  			}
  2748  		}
  2749  	case reflect.Struct, reflect.Func:
  2750  		if v.Len > int64(len(v.Children)) { // Not fully loaded
  2751  			if len(v.Children) == 0 { // Fully missing
  2752  				value = reloadVariable(v, qualifiedNameOrExpr)
  2753  			} else { // Partially missing (TODO)
  2754  				value = fmt.Sprintf("(loaded %d/%d) ", len(v.Children), v.Len) + value
  2755  			}
  2756  		}
  2757  		if len(v.Children) > 0 {
  2758  			variablesReference = maybeCreateVariableHandle(v)
  2759  		}
  2760  	case reflect.Complex64, reflect.Complex128:
  2761  		v.Children = make([]proc.Variable, 2)
  2762  		v.Children[0].Name = "real"
  2763  		v.Children[0].Value = constant.Real(v.Value)
  2764  		v.Children[1].Name = "imaginary"
  2765  		v.Children[1].Value = constant.Imag(v.Value)
  2766  		if v.Kind == reflect.Complex64 {
  2767  			v.Children[0].Kind = reflect.Float32
  2768  			v.Children[1].Kind = reflect.Float32
  2769  		} else {
  2770  			v.Children[0].Kind = reflect.Float64
  2771  			v.Children[1].Kind = reflect.Float64
  2772  		}
  2773  		fallthrough
  2774  	default: // Complex, Scalar, Chan
  2775  		if len(v.Children) > 0 {
  2776  			variablesReference = maybeCreateVariableHandle(v)
  2777  		}
  2778  	}
  2779  
  2780  	// By default, only values of variables that have children can be truncated.
  2781  	// If showFullValue is set, then all value strings are not truncated.
  2782  	canTruncateValue := showFullValue&opts == 0
  2783  	if len(value) > maxVarValueLen && canTruncateValue && canHaveRef {
  2784  		value = value[:maxVarValueLen] + "..."
  2785  	}
  2786  	return value, variablesReference
  2787  }
  2788  
  2789  // onEvaluateRequest handles 'evaluate' requests.
  2790  // This is a mandatory request to support.
  2791  // Support the following expressions:
  2792  //
  2793  //   - {expression} - evaluates the expression and returns the result as a variable
  2794  //   - call {function} - injects a function call and returns the result as a variable
  2795  //   - config {expression} - updates configuration parameters
  2796  //
  2797  // TODO(polina): users have complained about having to click to expand multi-level
  2798  // variables, so consider also adding the following:
  2799  //
  2800  //   - print {expression} - return the result as a string like from dlv cli
  2801  func (s *Session) onEvaluateRequest(request *dap.EvaluateRequest) {
  2802  	showErrorToUser := request.Arguments.Context != "watch" && request.Arguments.Context != "repl" && request.Arguments.Context != "hover"
  2803  	if s.debugger == nil {
  2804  		s.sendErrorResponseWithOpts(request.Request, UnableToEvaluateExpression, "Unable to evaluate expression", "debugger is nil", showErrorToUser)
  2805  		return
  2806  	}
  2807  
  2808  	// Default to the topmost stack frame of the current goroutine in case
  2809  	// no frame is specified (e.g. when stopped on entry or no call stack frame is expanded)
  2810  	goid, frame := -1, 0
  2811  	if sf, ok := s.stackFrameHandles.get(request.Arguments.FrameId); ok {
  2812  		goid = sf.(stackFrame).goroutineID
  2813  		frame = sf.(stackFrame).frameIndex
  2814  	}
  2815  
  2816  	response := &dap.EvaluateResponse{Response: *newResponse(request.Request)}
  2817  	expr := request.Arguments.Expression
  2818  
  2819  	if isConfig, err := regexp.MatchString(`^\s*dlv\s+\S+`, expr); err == nil && isConfig { // dlv {command}
  2820  		expr := strings.Replace(expr, "dlv ", "", 1)
  2821  		result, err := s.delveCmd(goid, frame, expr)
  2822  		if err != nil {
  2823  			s.sendErrorResponseWithOpts(request.Request, UnableToRunDlvCommand, "Unable to run dlv command", err.Error(), showErrorToUser)
  2824  			return
  2825  		}
  2826  		response.Body = dap.EvaluateResponseBody{
  2827  			Result: result,
  2828  		}
  2829  	} else if isCall, err := regexp.MatchString(`^\s*call\s+\S+`, expr); err == nil && isCall { // call {expression}
  2830  		expr := strings.Replace(expr, "call ", "", 1)
  2831  		_, retVars, err := s.doCall(goid, frame, expr)
  2832  		if err != nil {
  2833  			s.sendErrorResponseWithOpts(request.Request, UnableToEvaluateExpression, "Unable to evaluate expression", err.Error(), showErrorToUser)
  2834  			return
  2835  		}
  2836  		// The call completed, and we can reply with its return values (if any)
  2837  		if len(retVars) > 0 {
  2838  			// Package one or more return values in a single scope-like nameless variable
  2839  			// that preserves their names.
  2840  			retVarsAsVar := &proc.Variable{Children: slicePtrVarToSliceVar(retVars)}
  2841  			// As a shortcut also express the return values as a single string.
  2842  			retVarsAsStr := ""
  2843  			for _, v := range retVars {
  2844  				retVarsAsStr += s.convertVariableToString(v) + ", "
  2845  			}
  2846  			response.Body = dap.EvaluateResponseBody{
  2847  				Result:             strings.TrimRight(retVarsAsStr, ", "),
  2848  				VariablesReference: s.variableHandles.create(&fullyQualifiedVariable{retVarsAsVar, "", false /*not a scope*/, 0}),
  2849  			}
  2850  		}
  2851  	} else { // {expression}
  2852  		exprVar, err := s.debugger.EvalVariableInScope(int64(goid), frame, 0, expr, DefaultLoadConfig)
  2853  		if err != nil {
  2854  			s.sendErrorResponseWithOpts(request.Request, UnableToEvaluateExpression, "Unable to evaluate expression", err.Error(), showErrorToUser)
  2855  			return
  2856  		}
  2857  
  2858  		ctxt := request.Arguments.Context
  2859  		switch ctxt {
  2860  		case "repl", "variables", "hover", "clipboard":
  2861  			if exprVar.Kind == reflect.String {
  2862  				if strVal := constant.StringVal(exprVar.Value); exprVar.Len > int64(len(strVal)) {
  2863  					// Reload the string value with a bigger limit.
  2864  					loadCfg := DefaultLoadConfig
  2865  					loadCfg.MaxStringLen = maxSingleStringLen
  2866  					if v, err := s.debugger.EvalVariableInScope(int64(goid), frame, 0, request.Arguments.Expression, loadCfg); err != nil {
  2867  						s.config.log.Debugf("Failed to load more for %v: %v", request.Arguments.Expression, err)
  2868  					} else {
  2869  						exprVar = v
  2870  					}
  2871  				}
  2872  			}
  2873  		}
  2874  		var opts convertVariableFlags
  2875  		// Send the full value when the context is "clipboard" or "variables" since
  2876  		// these contexts are used to copy the value.
  2877  		if ctxt == "clipboard" || ctxt == "variables" {
  2878  			opts |= showFullValue
  2879  		}
  2880  		exprVal, exprRef := s.convertVariableWithOpts(exprVar, fmt.Sprintf("(%s)", request.Arguments.Expression), opts)
  2881  		response.Body = dap.EvaluateResponseBody{Result: exprVal, Type: s.getTypeIfSupported(exprVar), VariablesReference: exprRef, IndexedVariables: getIndexedVariableCount(exprVar), NamedVariables: getNamedVariableCount(exprVar)}
  2882  	}
  2883  	s.send(response)
  2884  }
  2885  
  2886  func (s *Session) doCall(goid, frame int, expr string) (*api.DebuggerState, []*proc.Variable, error) {
  2887  	// This call might be evaluated in the context of the frame that is not topmost
  2888  	// if the editor is set to view the variables for one of the parent frames.
  2889  	// If the call expression refers to any of these variables, unlike regular
  2890  	// expressions, it will evaluate them in the context of the topmost frame,
  2891  	// and the user will get an unexpected result or an unexpected symbol error.
  2892  	// We prevent this but disallowing any frames other than topmost.
  2893  	if frame > 0 {
  2894  		return nil, nil, fmt.Errorf("call is only supported with topmost stack frame")
  2895  	}
  2896  	stateBeforeCall, err := s.debugger.State( /*nowait*/ true)
  2897  	if err != nil {
  2898  		return nil, nil, err
  2899  	}
  2900  	// The return values of injected function calls are volatile.
  2901  	// Load as much useful data as possible.
  2902  	// TODO: investigate whether we need to increase other limits. For example,
  2903  	// the return value is a pointer to a temporary object, which can become
  2904  	// invalid by other injected function calls. Do we care about such use cases?
  2905  	loadCfg := DefaultLoadConfig
  2906  	loadCfg.MaxStringLen = maxStringLenInCallRetVars
  2907  
  2908  	// TODO(polina): since call will resume execution of all goroutines,
  2909  	// we should do this asynchronously and send a continued event to the
  2910  	// editor, followed by a stop event when the call completes.
  2911  	state, err := s.debugger.Command(&api.DebuggerCommand{
  2912  		Name:                 api.Call,
  2913  		ReturnInfoLoadConfig: api.LoadConfigFromProc(&loadCfg),
  2914  		Expr:                 expr,
  2915  		UnsafeCall:           false,
  2916  		GoroutineID:          int64(goid),
  2917  	}, nil)
  2918  	if processExited(state, err) {
  2919  		s.preTerminatedWG.Wait()
  2920  		e := &dap.TerminatedEvent{Event: *newEvent("terminated")}
  2921  		s.send(e)
  2922  		return nil, nil, errors.New("terminated")
  2923  	}
  2924  	if err != nil {
  2925  		return nil, nil, err
  2926  	}
  2927  
  2928  	// After the call is done, the goroutine where we injected the call should
  2929  	// return to the original stopped line with return values. However,
  2930  	// it is not guaranteed to be selected due to the possibility of the
  2931  	// of simultaneous breakpoints. Therefore, we check all threads.
  2932  	var retVars []*proc.Variable
  2933  	found := false
  2934  	for _, t := range state.Threads {
  2935  		if t.GoroutineID == stateBeforeCall.SelectedGoroutine.ID &&
  2936  			t.Line == stateBeforeCall.SelectedGoroutine.CurrentLoc.Line && t.CallReturn {
  2937  			found = true
  2938  			// The call completed. Get the return values.
  2939  			retVars, err = s.debugger.FindThreadReturnValues(t.ID, loadCfg)
  2940  			if err != nil {
  2941  				return nil, nil, err
  2942  			}
  2943  			break
  2944  		}
  2945  	}
  2946  	// Normal function calls expect return values, but call commands
  2947  	// used for variable assignments do not return a value when they succeed.
  2948  	// In go '=' is not an operator. Check if go/parser complains.
  2949  	// If the above Call command passed but the expression is not a valid
  2950  	// go expression, we just handled a variable assignment request.
  2951  	isAssignment := false
  2952  	if _, err := parser.ParseExpr(expr); err != nil {
  2953  		isAssignment = true
  2954  	}
  2955  
  2956  	// note: as described in https://github.com/golang/go/issues/25578, function call injection
  2957  	// causes to resume the entire Go process. Due to this limitation, there is no guarantee
  2958  	// that the process is in the same state even after the injected call returns normally
  2959  	// without any surprises such as breakpoints or panic. To handle this correctly we need
  2960  	// to reset all the handles (both variables and stack frames).
  2961  	//
  2962  	// We considered sending a stopped event after each call unconditionally, but a stopped
  2963  	// event can be expensive and can interact badly with the client-side optimization
  2964  	// to refresh information. For example, VS Code reissues scopes/evaluate (for watch) after
  2965  	// completing a setVariable or evaluate request for repl context. Thus, for now, we
  2966  	// do not trigger a stopped event and hope editors to refetch the updated state as soon
  2967  	// as the user resumes debugging.
  2968  
  2969  	if !found || !isAssignment && retVars == nil {
  2970  		// The call got interrupted by a stop (e.g. breakpoint in injected
  2971  		// function call or in another goroutine).
  2972  		s.resetHandlesForStoppedEvent()
  2973  		s.sendStoppedEvent(state)
  2974  
  2975  		// TODO(polina): once this is asynchronous, we could wait to reply until the user
  2976  		// continues, call ends, original stop point is hit and return values are available
  2977  		// instead of returning an error 'call stopped' here.
  2978  		return nil, nil, errors.New("call stopped")
  2979  	}
  2980  	return state, retVars, nil
  2981  }
  2982  
  2983  func (s *Session) sendStoppedEvent(state *api.DebuggerState) {
  2984  	stopped := &dap.StoppedEvent{Event: *newEvent("stopped")}
  2985  	stopped.Body.AllThreadsStopped = true
  2986  	stopped.Body.ThreadId = int(stoppedGoroutineID(state))
  2987  	stopped.Body.Reason = s.debugger.StopReason().String()
  2988  	s.send(stopped)
  2989  }
  2990  
  2991  // onTerminateRequest sends a not-yet-implemented error response.
  2992  // Capability 'supportsTerminateRequest' is not set in 'initialize' response.
  2993  func (s *Session) onTerminateRequest(request *dap.TerminateRequest) {
  2994  	s.sendNotYetImplementedErrorResponse(request.Request)
  2995  }
  2996  
  2997  // onRestartRequest sends a not-yet-implemented error response
  2998  // Capability 'supportsRestartRequest' is not set in 'initialize' response.
  2999  func (s *Session) onRestartRequest(request *dap.RestartRequest) {
  3000  	s.sendNotYetImplementedErrorResponse(request.Request)
  3001  }
  3002  
  3003  // onStepBackRequest handles 'stepBack' request.
  3004  // This is an optional request enabled by capability 'supportsStepBackRequest'.
  3005  func (s *Session) onStepBackRequest(request *dap.StepBackRequest, allowNextStateChange *syncflag) {
  3006  	s.sendStepResponse(request.Arguments.ThreadId, &dap.StepBackResponse{Response: *newResponse(request.Request)})
  3007  	s.stepUntilStopAndNotify(api.ReverseNext, request.Arguments.ThreadId, request.Arguments.Granularity, allowNextStateChange)
  3008  }
  3009  
  3010  // onReverseContinueRequest performs a rewind command call up to the previous
  3011  // breakpoint or the start of the process
  3012  // This is an optional request enabled by capability 'supportsStepBackRequest'.
  3013  func (s *Session) onReverseContinueRequest(request *dap.ReverseContinueRequest, allowNextStateChange *syncflag) {
  3014  	s.send(&dap.ReverseContinueResponse{
  3015  		Response: *newResponse(request.Request),
  3016  	})
  3017  	s.runUntilStopAndNotify(api.Rewind, allowNextStateChange)
  3018  }
  3019  
  3020  // computeEvaluateName finds the named child, and computes its evaluate name.
  3021  func (s *Session) computeEvaluateName(v *fullyQualifiedVariable, cname string) (string, error) {
  3022  	children := s.childrenToDAPVariables(v)
  3023  	for _, c := range children {
  3024  		if c.Name == cname {
  3025  			if c.EvaluateName != "" {
  3026  				return c.EvaluateName, nil
  3027  			}
  3028  			return "", errors.New("cannot set the variable without evaluate name")
  3029  		}
  3030  	}
  3031  	return "", errors.New("failed to find the named variable")
  3032  }
  3033  
  3034  // onSetVariableRequest handles 'setVariable' requests.
  3035  func (s *Session) onSetVariableRequest(request *dap.SetVariableRequest) {
  3036  	arg := request.Arguments
  3037  
  3038  	v, ok := s.variableHandles.get(arg.VariablesReference)
  3039  	if !ok {
  3040  		s.sendErrorResponse(request.Request, UnableToSetVariable, "Unable to lookup variable", fmt.Sprintf("unknown reference %d", arg.VariablesReference))
  3041  		return
  3042  	}
  3043  	// We need to translate the arg.Name to its evaluateName if the name
  3044  	// refers to a field or element of a variable.
  3045  	// https://github.com/microsoft/vscode/issues/120774
  3046  	evaluateName, err := s.computeEvaluateName(v, arg.Name)
  3047  	if err != nil {
  3048  		s.sendErrorResponse(request.Request, UnableToSetVariable, "Unable to set variable", err.Error())
  3049  		return
  3050  	}
  3051  
  3052  	// By running EvalVariableInScope, we get the type info of the variable
  3053  	// that can be accessed with the evaluateName, and ensure the variable we are
  3054  	// trying to update is valid and accessible from the top most frame & the
  3055  	// current goroutine.
  3056  	goid, frame := -1, 0
  3057  	evaluated, err := s.debugger.EvalVariableInScope(int64(goid), frame, 0, evaluateName, DefaultLoadConfig)
  3058  	if err != nil {
  3059  		s.sendErrorResponse(request.Request, UnableToSetVariable, "Unable to lookup variable", err.Error())
  3060  		return
  3061  	}
  3062  
  3063  	useFnCall := false
  3064  	switch evaluated.Kind {
  3065  	case reflect.String:
  3066  		useFnCall = true
  3067  	default:
  3068  		// TODO(hyangah): it's possible to set a non-string variable using (`call i = fn()`)
  3069  		// and we don't support it through the Set Variable request yet.
  3070  		// If we want to support it for non-string types, we need to parse arg.Value.
  3071  	}
  3072  
  3073  	if useFnCall {
  3074  		// TODO(hyangah): function call injection currently allows to assign return values of
  3075  		// a function call to variables. So, curious users would find set variable
  3076  		// on string would accept expression like `fn()`.
  3077  		if state, retVals, err := s.doCall(goid, frame, fmt.Sprintf("%v=%v", evaluateName, arg.Value)); err != nil {
  3078  			s.sendErrorResponse(request.Request, UnableToSetVariable, "Unable to set variable", err.Error())
  3079  			return
  3080  		} else if retVals != nil {
  3081  			// The assignment expression isn't supposed to return values, but we got them.
  3082  			// That indicates something went wrong (e.g. panic).
  3083  			// TODO: isn't it simpler to do this in s.doCall?
  3084  			s.resetHandlesForStoppedEvent()
  3085  			s.sendStoppedEvent(state)
  3086  
  3087  			var r []string
  3088  			for _, v := range retVals {
  3089  				r = append(r, s.convertVariableToString(v))
  3090  			}
  3091  			msg := "interrupted"
  3092  			if len(r) > 0 {
  3093  				msg = "interrupted:" + strings.Join(r, ", ")
  3094  			}
  3095  
  3096  			s.sendErrorResponse(request.Request, UnableToSetVariable, "Unable to set variable", msg)
  3097  			return
  3098  		}
  3099  	} else {
  3100  		if err := s.debugger.SetVariableInScope(int64(goid), frame, 0, evaluateName, arg.Value); err != nil {
  3101  			s.sendErrorResponse(request.Request, UnableToSetVariable, "Unable to set variable", err.Error())
  3102  			return
  3103  		}
  3104  	}
  3105  	// * Note on inconsistent state after set variable:
  3106  	//
  3107  	// The variable handles may be in inconsistent state - for example,
  3108  	// let's assume there are two aliased variables pointing to the same
  3109  	// memory and both are already loaded and cached in the variable handle.
  3110  	// VSCode tries to locally update the UI when the set variable
  3111  	// request succeeds, and may issue additional scopes or evaluate requests
  3112  	// to update the variable/watch sections if necessary.
  3113  	//
  3114  	// More complicated situation is when the set variable involves call
  3115  	// injection - after the injected call is completed, the debuggee can
  3116  	// be in a completely different state (see the note in doCall) due to
  3117  	// how the call injection is implemented. Ideally, we need to also refresh
  3118  	// the stack frames but that is complicated. For now, we don't try to actively
  3119  	// invalidate this state hoping that the editors will refetch the state
  3120  	// as soon as the user resumes debugging.
  3121  
  3122  	response := &dap.SetVariableResponse{Response: *newResponse(request.Request)}
  3123  	response.Body.Value = arg.Value
  3124  	// TODO(hyangah): instead of arg.Value, reload the variable and return
  3125  	// the presentation of the new value.
  3126  	s.send(response)
  3127  }
  3128  
  3129  // onSetExpression sends a not-yet-implemented error response.
  3130  // Capability 'supportsSetExpression' is not set 'initialize' response.
  3131  func (s *Session) onSetExpressionRequest(request *dap.SetExpressionRequest) {
  3132  	s.sendNotYetImplementedErrorResponse(request.Request)
  3133  }
  3134  
  3135  // onLoadedSourcesRequest sends a not-yet-implemented error response.
  3136  // Capability 'supportsLoadedSourcesRequest' is not set 'initialize' response.
  3137  func (s *Session) onLoadedSourcesRequest(request *dap.LoadedSourcesRequest) {
  3138  	s.sendNotYetImplementedErrorResponse(request.Request)
  3139  }
  3140  
  3141  // onReadMemoryRequest sends a not-yet-implemented error response.
  3142  // Capability 'supportsReadMemoryRequest' is not set 'initialize' response.
  3143  func (s *Session) onReadMemoryRequest(request *dap.ReadMemoryRequest) {
  3144  	s.sendNotYetImplementedErrorResponse(request.Request)
  3145  }
  3146  
  3147  var invalidInstruction = dap.DisassembledInstruction{
  3148  	Instruction: "invalid instruction",
  3149  }
  3150  
  3151  // onDisassembleRequest handles 'disassemble' requests.
  3152  // Capability 'supportsDisassembleRequest' is set in 'initialize' response.
  3153  func (s *Session) onDisassembleRequest(request *dap.DisassembleRequest) {
  3154  	// TODO(suzmue): microsoft/vscode#129655 is discussing the difference between
  3155  	// memory reference and instructionPointerReference, which are currently
  3156  	// being used interchangeably by vscode.
  3157  	addr, err := strconv.ParseUint(request.Arguments.MemoryReference, 0, 64)
  3158  	if err != nil {
  3159  		s.sendErrorResponse(request.Request, UnableToDisassemble, "Unable to disassemble", err.Error())
  3160  		return
  3161  	}
  3162  
  3163  	// If the requested memory address is an invalid location, return all invalid instructions.
  3164  	// TODO(suzmue): consider adding fake addresses that would allow us to receive out of bounds
  3165  	// requests that include valid instructions designated by InstructionOffset or InstructionCount.
  3166  	if addr == 0 || addr == uint64(math.MaxUint64) {
  3167  		instructions := make([]dap.DisassembledInstruction, request.Arguments.InstructionCount)
  3168  		for i := range instructions {
  3169  			instructions[i] = invalidInstruction
  3170  			instructions[i].Address = request.Arguments.MemoryReference
  3171  		}
  3172  		response := &dap.DisassembleResponse{
  3173  			Response: *newResponse(request.Request),
  3174  			Body: dap.DisassembleResponseBody{
  3175  				Instructions: instructions,
  3176  			},
  3177  		}
  3178  		s.send(response)
  3179  		return
  3180  	}
  3181  
  3182  	start := addr
  3183  	maxInstructionLength := s.debugger.Target().BinInfo().Arch.MaxInstructionLength()
  3184  	byteOffset := request.Arguments.InstructionOffset * maxInstructionLength
  3185  	// Adjust the offset to include instructions before the requested address.
  3186  	if byteOffset < 0 {
  3187  		start = uint64(int(addr) + byteOffset)
  3188  	}
  3189  	// Adjust the number of instructions to include enough instructions after
  3190  	// the requested address.
  3191  	count := request.Arguments.InstructionCount
  3192  	if byteOffset > 0 {
  3193  		count += byteOffset
  3194  	}
  3195  	end := uint64(int(addr) + count*maxInstructionLength)
  3196  
  3197  	// Make sure the PCs are lined up with instructions.
  3198  	start, end = alignPCs(s.debugger.Target().BinInfo(), start, end)
  3199  
  3200  	// Disassemble the instructions
  3201  	procInstructions, err := s.debugger.Disassemble(-1, start, end)
  3202  	if err != nil {
  3203  		s.sendErrorResponse(request.Request, UnableToDisassemble, "Unable to disassemble", err.Error())
  3204  		return
  3205  	}
  3206  
  3207  	// Find the section of instructions that were requested.
  3208  	procInstructions, offset, err := findInstructions(procInstructions, addr, request.Arguments.InstructionOffset, request.Arguments.InstructionCount)
  3209  	if err != nil {
  3210  		s.sendErrorResponse(request.Request, UnableToDisassemble, "Unable to disassemble", err.Error())
  3211  		return
  3212  	}
  3213  
  3214  	// Turn the given range of instructions into dap instructions.
  3215  	instructions := make([]dap.DisassembledInstruction, request.Arguments.InstructionCount)
  3216  	lastFile, lastLine := "", -1
  3217  	for i := range instructions {
  3218  		// i is not in a valid range, use an address that is just before or after
  3219  		// the range. This ensures that it can still be parsed as an int.
  3220  		if i < offset {
  3221  			// i is not in a valid range.
  3222  			instructions[i] = invalidInstruction
  3223  			instructions[i].Address = "0x0"
  3224  			continue
  3225  		}
  3226  		if (i - offset) >= len(procInstructions) {
  3227  			// i is not in a valid range.
  3228  			instructions[i] = invalidInstruction
  3229  			instructions[i].Address = fmt.Sprintf("%#x", uint64(math.MaxUint64))
  3230  			continue
  3231  
  3232  		}
  3233  		instruction := api.ConvertAsmInstruction(procInstructions[i-offset], s.debugger.AsmInstructionText(&procInstructions[i-offset], proc.GoFlavour))
  3234  		instructions[i] = dap.DisassembledInstruction{
  3235  			Address:          fmt.Sprintf("%#x", instruction.Loc.PC),
  3236  			InstructionBytes: fmt.Sprintf("%x", instruction.Bytes),
  3237  			Instruction:      instruction.Text,
  3238  		}
  3239  		// Only set the location on the first instruction for a given line.
  3240  		if instruction.Loc.File != lastFile || instruction.Loc.Line != lastLine {
  3241  			instructions[i].Location = &dap.Source{Path: instruction.Loc.File}
  3242  			instructions[i].Line = instruction.Loc.Line
  3243  			lastFile, lastLine = instruction.Loc.File, instruction.Loc.Line
  3244  		}
  3245  	}
  3246  
  3247  	response := &dap.DisassembleResponse{
  3248  		Response: *newResponse(request.Request),
  3249  		Body: dap.DisassembleResponseBody{
  3250  			Instructions: instructions,
  3251  		},
  3252  	}
  3253  	s.send(response)
  3254  }
  3255  
  3256  func findInstructions(procInstructions []proc.AsmInstruction, addr uint64, instructionOffset, count int) ([]proc.AsmInstruction, int, error) {
  3257  	ref := sort.Search(len(procInstructions), func(i int) bool {
  3258  		return procInstructions[i].Loc.PC >= addr
  3259  	})
  3260  	if ref == len(procInstructions) || procInstructions[ref].Loc.PC != addr {
  3261  		return nil, -1, fmt.Errorf("could not find memory reference")
  3262  	}
  3263  	// offset is the number of instructions that should appear before the first instruction
  3264  	// returned by findInstructions.
  3265  	offset := 0
  3266  	if ref+instructionOffset < 0 {
  3267  		offset = -(ref + instructionOffset)
  3268  	}
  3269  	// Figure out the index to slice at.
  3270  	startIdx := ref + instructionOffset
  3271  	endIdx := ref + instructionOffset + count
  3272  	if endIdx <= 0 || startIdx >= len(procInstructions) {
  3273  		return []proc.AsmInstruction{}, 0, nil
  3274  	}
  3275  	// Adjust start and end to be inbounds.
  3276  	if startIdx < 0 {
  3277  		offset = -startIdx
  3278  		startIdx = 0
  3279  	}
  3280  	if endIdx > len(procInstructions) {
  3281  		endIdx = len(procInstructions)
  3282  	}
  3283  	return procInstructions[startIdx:endIdx], offset, nil
  3284  }
  3285  
  3286  func getValidRange(bi *proc.BinaryInfo) (uint64, uint64) {
  3287  	return bi.Functions[0].Entry, bi.Functions[len(bi.Functions)-1].End
  3288  }
  3289  
  3290  func alignPCs(bi *proc.BinaryInfo, start, end uint64) (uint64, uint64) {
  3291  	// We want to find the function locations position that would enclose
  3292  	// the range from start to end.
  3293  	//
  3294  	// Example:
  3295  	//
  3296  	// 0x0000	instruction (func1)
  3297  	// 0x0004	instruction (func1)
  3298  	// 0x0008	instruction (func1)
  3299  	// 0x000c	nop
  3300  	// 0x000e	nop
  3301  	// 0x0000	nop
  3302  	// 0x0002	nop
  3303  	// 0x0004	instruction (func2)
  3304  	// 0x0008	instruction (func2)
  3305  	// 0x000c	instruction (func2)
  3306  	//
  3307  	// start values:
  3308  	// < 0x0000			at func1.Entry	=	0x0000
  3309  	// 0x0000-0x000b	at func1.Entry	=	0x0000
  3310  	// 0x000c-0x0003	at func1.End	=	0x000c
  3311  	// 0x0004-0x000f	at func2.Entry	=	0x0004
  3312  	// > 0x000f			at func2.End	=	0x0010
  3313  	//
  3314  	// end values:
  3315  	// < 0x0000			at func1.Entry	=	0x0000
  3316  	// 0x0000-0x000b	at func1.End	=	0x0000
  3317  	// 0x000c-0x0003	at func2.Entry	=	0x000c
  3318  	// 0x0004-0x000f	at func2.End	=	0x0004
  3319  	// > 0x000f			at func2.End	=	0x0004
  3320  	// Handle start values:
  3321  	fn := bi.PCToFunc(start)
  3322  	if fn != nil {
  3323  		// start is in a function.
  3324  		start = fn.Entry
  3325  	} else if b, pc := checkOutOfAddressSpace(start, bi); b {
  3326  		start = pc
  3327  	} else {
  3328  		// Otherwise it must come after some function.
  3329  		i := sort.Search(len(bi.Functions), func(i int) bool {
  3330  			fn := bi.Functions[len(bi.Functions)-(i+1)]
  3331  			return start >= fn.End
  3332  		})
  3333  		start = bi.Functions[len(bi.Functions)-(i+1)].Entry
  3334  	}
  3335  
  3336  	// Handle end values:
  3337  	if fn := bi.PCToFunc(end); fn != nil {
  3338  		// end is in a function.
  3339  		end = fn.End
  3340  	} else if b, pc := checkOutOfAddressSpace(end, bi); b {
  3341  		end = pc
  3342  	} else {
  3343  		// Otherwise it must come before some function.
  3344  		i := sort.Search(len(bi.Functions), func(i int) bool {
  3345  			fn := bi.Functions[i]
  3346  			return end < fn.Entry
  3347  		})
  3348  		end = bi.Functions[i].Entry
  3349  		const limit = 10 * 1024
  3350  		if end-start > limit {
  3351  			end = start + limit
  3352  		}
  3353  	}
  3354  
  3355  	return start, end
  3356  }
  3357  
  3358  func checkOutOfAddressSpace(pc uint64, bi *proc.BinaryInfo) (bool, uint64) {
  3359  	entry, end := getValidRange(bi)
  3360  	if pc < entry {
  3361  		return true, entry
  3362  	}
  3363  	if pc >= end {
  3364  		return true, end
  3365  	}
  3366  	return false, pc
  3367  }
  3368  
  3369  // onCancelRequest sends a not-yet-implemented error response.
  3370  // Capability 'supportsCancelRequest' is not set 'initialize' response.
  3371  func (s *Session) onCancelRequest(request *dap.CancelRequest) {
  3372  	s.sendNotYetImplementedErrorResponse(request.Request)
  3373  }
  3374  
  3375  // onExceptionInfoRequest handles 'exceptionInfo' requests.
  3376  // Capability 'supportsExceptionInfoRequest' is set in 'initialize' response.
  3377  func (s *Session) onExceptionInfoRequest(request *dap.ExceptionInfoRequest) {
  3378  	goroutineID := int64(request.Arguments.ThreadId)
  3379  	var body dap.ExceptionInfoResponseBody
  3380  	// Get the goroutine and the current state.
  3381  	g, err := s.debugger.FindGoroutine(goroutineID)
  3382  	if err != nil {
  3383  		s.sendErrorResponse(request.Request, UnableToGetExceptionInfo, "Unable to get exception info", err.Error())
  3384  		return
  3385  	}
  3386  	if g == nil {
  3387  		s.sendErrorResponse(request.Request, UnableToGetExceptionInfo, "Unable to get exception info", fmt.Sprintf("could not find goroutine %d", goroutineID))
  3388  		return
  3389  	}
  3390  	var bpState *proc.BreakpointState
  3391  	if g.Thread != nil {
  3392  		bpState = g.Thread.Breakpoint()
  3393  	}
  3394  	// Check if this goroutine ID is stopped at a breakpoint.
  3395  	includeStackTrace := true
  3396  	if bpState != nil && bpState.Breakpoint != nil && bpState.Breakpoint.Logical != nil && (bpState.Breakpoint.Logical.Name == proc.FatalThrow || bpState.Breakpoint.Logical.Name == proc.UnrecoveredPanic) {
  3397  		switch bpState.Breakpoint.Logical.Name {
  3398  		case proc.FatalThrow:
  3399  			body.ExceptionId = "fatal error"
  3400  			body.Description, err = s.throwReason(goroutineID)
  3401  			if err != nil {
  3402  				body.Description = fmt.Sprintf("Error getting throw reason: %s", err.Error())
  3403  				// This is not currently working for Go 1.16.
  3404  				ver := goversion.ParseProducer(s.debugger.TargetGoVersion())
  3405  				if ver.Major == 1 && ver.Minor == 16 {
  3406  					body.Description = "Throw reason unavailable, see https://github.com/golang/go/issues/46425"
  3407  				}
  3408  			}
  3409  		case proc.UnrecoveredPanic:
  3410  			body.ExceptionId = "panic"
  3411  			// Attempt to get the value of the panic message.
  3412  			body.Description, err = s.panicReason(goroutineID)
  3413  			if err != nil {
  3414  				body.Description = fmt.Sprintf("Error getting panic message: %s", err.Error())
  3415  			}
  3416  		}
  3417  	} else {
  3418  		// If this thread is not stopped on a breakpoint, then a runtime error must have occurred.
  3419  		// If we do not have any error saved, or if this thread is not current thread,
  3420  		// return an error.
  3421  		if s.exceptionErr == nil {
  3422  			s.sendErrorResponse(request.Request, UnableToGetExceptionInfo, "Unable to get exception info", "no runtime error found")
  3423  			return
  3424  		}
  3425  
  3426  		state, err := s.debugger.State( /*nowait*/ true)
  3427  		if err != nil {
  3428  			s.sendErrorResponse(request.Request, UnableToGetExceptionInfo, "Unable to get exception info", err.Error())
  3429  			return
  3430  		}
  3431  		if s.exceptionErr.Error() != "next while nexting" && (state == nil || state.CurrentThread == nil || g.Thread == nil || state.CurrentThread.ID != g.Thread.ThreadID()) {
  3432  			s.sendErrorResponse(request.Request, UnableToGetExceptionInfo, "Unable to get exception info", fmt.Sprintf("no exception found for goroutine %d", goroutineID))
  3433  			return
  3434  		}
  3435  		body.ExceptionId = "runtime error"
  3436  		body.Description = s.exceptionErr.Error()
  3437  		if body.Description == "bad access" {
  3438  			body.Description = BetterBadAccessError
  3439  		}
  3440  		if body.Description == "next while nexting" {
  3441  			body.ExceptionId = "invalid command"
  3442  			body.Description = BetterNextWhileNextingError
  3443  			includeStackTrace = false
  3444  		}
  3445  	}
  3446  
  3447  	if includeStackTrace {
  3448  		body.Details = &dap.ExceptionDetails{}
  3449  		frames, err := s.stacktrace(goroutineID, g)
  3450  		if err != nil {
  3451  			body.Details.StackTrace = fmt.Sprintf("Error getting stack trace: %s", err.Error())
  3452  		} else {
  3453  			body.Details.StackTrace = frames
  3454  		}
  3455  	}
  3456  	response := &dap.ExceptionInfoResponse{
  3457  		Response: *newResponse(request.Request),
  3458  		Body:     body,
  3459  	}
  3460  	s.send(response)
  3461  }
  3462  
  3463  func (s *Session) stacktrace(goroutineID int64, g *proc.G) (string, error) {
  3464  	frames, err := s.debugger.Stacktrace(goroutineID, s.args.StackTraceDepth, 0)
  3465  	if err != nil {
  3466  		return "", err
  3467  	}
  3468  	apiFrames, err := s.debugger.ConvertStacktrace(frames, nil)
  3469  	if err != nil {
  3470  		return "", err
  3471  	}
  3472  
  3473  	var buf bytes.Buffer
  3474  	fmt.Fprintln(&buf, "Stack:")
  3475  	userLoc := g.UserCurrent()
  3476  	userFuncPkg := fnPackageName(&userLoc)
  3477  	api.PrintStack(s.toClientPath, &buf, apiFrames, "\t", false, api.StackTraceColors{}, func(s api.Stackframe) bool {
  3478  		// Include all stack frames if the stack trace is for a system goroutine,
  3479  		// otherwise, skip runtime stack frames.
  3480  		if userFuncPkg == "runtime" {
  3481  			return true
  3482  		}
  3483  		return s.Location.Function != nil && !strings.HasPrefix(s.Location.Function.Name(), "runtime.")
  3484  	})
  3485  	return buf.String(), nil
  3486  }
  3487  
  3488  func (s *Session) throwReason(goroutineID int64) (string, error) {
  3489  	return s.getExprString("s", goroutineID, 0)
  3490  }
  3491  
  3492  func (s *Session) panicReason(goroutineID int64) (string, error) {
  3493  	return s.getExprString("(*msgs).arg.(data)", goroutineID, 0)
  3494  }
  3495  
  3496  func (s *Session) getExprString(expr string, goroutineID int64, frame int) (string, error) {
  3497  	exprVar, err := s.debugger.EvalVariableInScope(goroutineID, frame, 0, expr, DefaultLoadConfig)
  3498  	if err != nil {
  3499  		return "", err
  3500  	}
  3501  	if exprVar.Value == nil {
  3502  		return "", exprVar.Unreadable
  3503  	}
  3504  	return exprVar.Value.String(), nil
  3505  }
  3506  
  3507  // sendErrorResponseWithOpts offers configuration options.
  3508  //
  3509  //	showUser - if true, the error will be shown to the user (e.g. via a visible pop-up)
  3510  func (s *Session) sendErrorResponseWithOpts(request dap.Request, id int, summary, details string, showUser bool) {
  3511  	er := &dap.ErrorResponse{}
  3512  	er.Type = "response"
  3513  	er.Command = request.Command
  3514  	er.RequestSeq = request.Seq
  3515  	er.Success = false
  3516  	er.Message = summary
  3517  	er.Body.Error = &dap.ErrorMessage{
  3518  		Id:       id,
  3519  		Format:   fmt.Sprintf("%s: %s", summary, details),
  3520  		ShowUser: showUser,
  3521  	}
  3522  	s.config.log.Debug(er.Body.Error.Format)
  3523  	s.send(er)
  3524  }
  3525  
  3526  // sendErrorResponse sends an error response with showUser disabled (default).
  3527  func (s *Session) sendErrorResponse(request dap.Request, id int, summary, details string) {
  3528  	s.sendErrorResponseWithOpts(request, id, summary, details, false /*showUser*/)
  3529  }
  3530  
  3531  // sendShowUserErrorResponse sends an error response with showUser enabled.
  3532  func (s *Session) sendShowUserErrorResponse(request dap.Request, id int, summary, details string) {
  3533  	s.sendErrorResponseWithOpts(request, id, summary, details, true /*showUser*/)
  3534  }
  3535  
  3536  // sendInternalErrorResponse sends an "internal error" response back to the client.
  3537  // We only take a seq here because we don't want to make assumptions about the
  3538  // kind of message received by the server that this error is a reply to.
  3539  func (s *Session) sendInternalErrorResponse(seq int, details string) {
  3540  	er := &dap.ErrorResponse{}
  3541  	er.Type = "response"
  3542  	er.RequestSeq = seq
  3543  	er.Success = false
  3544  	er.Message = "Internal Error"
  3545  	er.Body.Error = &dap.ErrorMessage{
  3546  		Id:     InternalError,
  3547  		Format: fmt.Sprintf("%s: %s", er.Message, details),
  3548  	}
  3549  	s.config.log.Debug(er.Body.Error.Format)
  3550  	s.send(er)
  3551  }
  3552  
  3553  func (s *Session) sendUnsupportedErrorResponse(request dap.Request) {
  3554  	s.sendErrorResponse(request, UnsupportedCommand, "Unsupported command",
  3555  		fmt.Sprintf("cannot process %q request", request.Command))
  3556  }
  3557  
  3558  func (s *Session) sendNotYetImplementedErrorResponse(request dap.Request) {
  3559  	s.sendErrorResponse(request, NotYetImplemented, "Not yet implemented",
  3560  		fmt.Sprintf("cannot process %q request", request.Command))
  3561  }
  3562  
  3563  func newResponse(request dap.Request) *dap.Response {
  3564  	return &dap.Response{
  3565  		ProtocolMessage: dap.ProtocolMessage{
  3566  			Seq:  0,
  3567  			Type: "response",
  3568  		},
  3569  		Command:    request.Command,
  3570  		RequestSeq: request.Seq,
  3571  		Success:    true,
  3572  	}
  3573  }
  3574  
  3575  func newEvent(event string) *dap.Event {
  3576  	return &dap.Event{
  3577  		ProtocolMessage: dap.ProtocolMessage{
  3578  			Seq:  0,
  3579  			Type: "event",
  3580  		},
  3581  		Event: event,
  3582  	}
  3583  }
  3584  
  3585  const BetterBadAccessError = `invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation]
  3586  Unable to propagate EXC_BAD_ACCESS signal to target process and panic (see https://gitlab.com/Raven-IO/raven-delve/issues/852)`
  3587  
  3588  const BetterNextWhileNextingError = `Unable to step while the previous step is interrupted by a breakpoint.
  3589  Use 'Continue' to resume the original step command.`
  3590  
  3591  func (s *Session) resetHandlesForStoppedEvent() {
  3592  	s.stackFrameHandles.reset()
  3593  	s.variableHandles.reset()
  3594  	s.exceptionErr = nil
  3595  }
  3596  
  3597  func processExited(state *api.DebuggerState, err error) bool {
  3598  	var errProcessExited proc.ErrProcessExited
  3599  	isexited := errors.As(err, &errProcessExited)
  3600  	return isexited || err == nil && state.Exited
  3601  }
  3602  
  3603  func (s *Session) setRunningCmd(running bool) {
  3604  	s.runningMu.Lock()
  3605  	defer s.runningMu.Unlock()
  3606  	s.runningCmd = running
  3607  }
  3608  
  3609  func (s *Session) isRunningCmd() bool {
  3610  	s.runningMu.Lock()
  3611  	defer s.runningMu.Unlock()
  3612  	return s.runningCmd
  3613  }
  3614  
  3615  func (s *Session) setHaltRequested(requested bool) {
  3616  	s.haltMu.Lock()
  3617  	defer s.haltMu.Unlock()
  3618  	s.haltRequested = requested
  3619  }
  3620  
  3621  func (s *Session) checkHaltRequested() bool {
  3622  	s.haltMu.Lock()
  3623  	defer s.haltMu.Unlock()
  3624  	return s.haltRequested
  3625  }
  3626  
  3627  // resumeOnce is a helper function to resume the execution
  3628  // of the target when the program is halted.
  3629  func (s *Session) resumeOnce(command string, allowNextStateChange *syncflag) (bool, *api.DebuggerState, error) {
  3630  	// No other goroutines should be able to try to resume
  3631  	// or halt execution while this goroutine is resuming
  3632  	// execution, so we do not miss those events.
  3633  	asyncSetupDone := make(chan struct{}, 1)
  3634  	defer closeIfOpen(asyncSetupDone)
  3635  	s.changeStateMu.Lock()
  3636  	go func() {
  3637  		defer s.changeStateMu.Unlock()
  3638  		defer allowNextStateChange.raise()
  3639  		<-asyncSetupDone
  3640  	}()
  3641  
  3642  	// There may have been a manual halt while the program was
  3643  	// stopped. If this happened, do not resume execution of
  3644  	// the program.
  3645  	if s.checkHaltRequested() {
  3646  		state, err := s.debugger.State(false)
  3647  		return false, state, err
  3648  	}
  3649  	state, err := s.debugger.Command(&api.DebuggerCommand{Name: command}, asyncSetupDone)
  3650  	return true, state, err
  3651  }
  3652  
  3653  // runUntilStopAndNotify runs a debugger command until it stops on
  3654  // termination, error, breakpoint, etc., when an appropriate
  3655  // event needs to be sent to the client. allowNextStateChange is
  3656  // a channel that will be closed to signal that an
  3657  // asynchronous command has completed setup or was interrupted
  3658  // due to an error, so the server is ready to receive new requests.
  3659  func (s *Session) runUntilStopAndNotify(command string, allowNextStateChange *syncflag) {
  3660  	state, err := s.runUntilStop(command, allowNextStateChange)
  3661  
  3662  	if s.conn.isClosed() {
  3663  		s.config.log.Debugf("connection %d closed - stopping %q command", s.id, command)
  3664  		return
  3665  	}
  3666  
  3667  	if processExited(state, err) {
  3668  		s.preTerminatedWG.Wait()
  3669  		s.send(&dap.TerminatedEvent{Event: *newEvent("terminated")})
  3670  		return
  3671  	}
  3672  
  3673  	stopReason := s.debugger.StopReason()
  3674  	file, line := "?", -1
  3675  	if state != nil && state.CurrentThread != nil {
  3676  		file, line = state.CurrentThread.File, state.CurrentThread.Line
  3677  	}
  3678  	s.config.log.Debugf("%q command stopped - reason %q, location %s:%d", command, stopReason, file, line)
  3679  
  3680  	s.resetHandlesForStoppedEvent()
  3681  	stopped := &dap.StoppedEvent{Event: *newEvent("stopped")}
  3682  	stopped.Body.AllThreadsStopped = true
  3683  
  3684  	if err == nil {
  3685  		if stopReason == proc.StopManual {
  3686  			if err := s.debugger.CancelNext(); err != nil {
  3687  				s.config.log.Error(err)
  3688  			} else {
  3689  				state.NextInProgress = false
  3690  			}
  3691  		}
  3692  		stopped.Body.ThreadId = int(stoppedGoroutineID(state))
  3693  
  3694  		switch stopReason {
  3695  		case proc.StopNextFinished:
  3696  			stopped.Body.Reason = "step"
  3697  		case proc.StopManual: // triggered by halt
  3698  			stopped.Body.Reason = "pause"
  3699  		case proc.StopUnknown: // can happen while terminating
  3700  			stopped.Body.Reason = "unknown"
  3701  		case proc.StopWatchpoint:
  3702  			stopped.Body.Reason = "data breakpoint"
  3703  		default:
  3704  			stopped.Body.Reason = "breakpoint"
  3705  			goid, bp := s.stoppedOnBreakpointGoroutineID(state)
  3706  			stopped.Body.ThreadId = int(goid)
  3707  			if bp != nil {
  3708  				switch bp.Name {
  3709  				case proc.FatalThrow:
  3710  					stopped.Body.Reason = "exception"
  3711  					stopped.Body.Description = "fatal error"
  3712  					stopped.Body.Text, _ = s.throwReason(int64(stopped.Body.ThreadId))
  3713  				case proc.UnrecoveredPanic:
  3714  					stopped.Body.Reason = "exception"
  3715  					stopped.Body.Description = "panic"
  3716  					stopped.Body.Text, _ = s.panicReason(int64(stopped.Body.ThreadId))
  3717  				}
  3718  				if strings.HasPrefix(bp.Name, functionBpPrefix) {
  3719  					stopped.Body.Reason = "function breakpoint"
  3720  				}
  3721  				if strings.HasPrefix(bp.Name, instructionBpPrefix) {
  3722  					stopped.Body.Reason = "instruction breakpoint"
  3723  				}
  3724  				stopped.Body.HitBreakpointIds = []int{bp.ID}
  3725  			}
  3726  		}
  3727  
  3728  		// Override the stop reason if there was a manual stop request.
  3729  		// TODO(suzmue): move this logic into the runUntilStop command
  3730  		// so that the stop reason is determined by that function which
  3731  		// has all the context.
  3732  		if stopped.Body.Reason != "exception" && s.checkHaltRequested() {
  3733  			s.config.log.Debugf("manual halt requested, stop reason %q converted to \"pause\"", stopped.Body.Reason)
  3734  			stopped.Body.Reason = "pause"
  3735  			stopped.Body.HitBreakpointIds = []int{}
  3736  		}
  3737  
  3738  	} else {
  3739  		s.exceptionErr = err
  3740  		s.config.log.Error("runtime error: ", err)
  3741  		stopped.Body.Reason = "exception"
  3742  		stopped.Body.Description = "runtime error"
  3743  		stopped.Body.Text = err.Error()
  3744  		// Special case in the spirit of https://github.com/microsoft/vscode-go/issues/1903
  3745  		if stopped.Body.Text == "bad access" {
  3746  			stopped.Body.Text = BetterBadAccessError
  3747  		}
  3748  		if stopped.Body.Text == "next while nexting" {
  3749  			stopped.Body.Description = "invalid command"
  3750  			stopped.Body.Text = BetterNextWhileNextingError
  3751  			s.logToConsole(fmt.Sprintf("%s: %s", stopped.Body.Description, stopped.Body.Text))
  3752  		}
  3753  
  3754  		state, err := s.debugger.State( /*nowait*/ true)
  3755  		if err == nil {
  3756  			stopped.Body.ThreadId = int(stoppedGoroutineID(state))
  3757  		}
  3758  	}
  3759  
  3760  	// NOTE: If we happen to be responding to another request with an is-running
  3761  	// error while this one completes, it is possible that the error response
  3762  	// will arrive after this stopped event.
  3763  	s.send(stopped)
  3764  
  3765  	// Send an output event with more information if next is in progress.
  3766  	if state != nil && state.NextInProgress {
  3767  		s.logToConsole("Step interrupted by a breakpoint. Use 'Continue' to resume the original step command.")
  3768  	}
  3769  }
  3770  
  3771  func (s *Session) runUntilStop(command string, allowNextStateChange *syncflag) (*api.DebuggerState, error) {
  3772  	// Clear any manual stop requests that came in before we started running.
  3773  	s.setHaltRequested(false)
  3774  
  3775  	s.setRunningCmd(true)
  3776  	defer s.setRunningCmd(false)
  3777  
  3778  	var state *api.DebuggerState
  3779  	var err error
  3780  	for s.isRunningCmd() {
  3781  		state, err = resumeOnceAndCheckStop(s, command, allowNextStateChange)
  3782  		command = api.DirectionCongruentContinue
  3783  	}
  3784  	return state, err
  3785  }
  3786  
  3787  // Make this a var, so it can be stubbed in testing.
  3788  var resumeOnceAndCheckStop = func(s *Session, command string, allowNextStateChange *syncflag) (*api.DebuggerState, error) {
  3789  	return s.resumeOnceAndCheckStop(command, allowNextStateChange)
  3790  }
  3791  
  3792  func (s *Session) resumeOnceAndCheckStop(command string, allowNextStateChange *syncflag) (*api.DebuggerState, error) {
  3793  	resumed, state, err := s.resumeOnce(command, allowNextStateChange)
  3794  	// We should not try to process the log points if the program was not
  3795  	// resumed or there was an error.
  3796  	if !resumed || processExited(state, err) || state == nil || err != nil || s.conn.isClosed() {
  3797  		s.setRunningCmd(false)
  3798  		return state, err
  3799  	}
  3800  
  3801  	s.handleLogPoints(state)
  3802  	gsOnBp := s.stoppedGs(state)
  3803  
  3804  	switch s.debugger.StopReason() {
  3805  	case proc.StopBreakpoint, proc.StopManual:
  3806  		// Make sure a real manual stop was requested or a real breakpoint was hit.
  3807  		if len(gsOnBp) > 0 || s.checkHaltRequested() {
  3808  			s.setRunningCmd(false)
  3809  		}
  3810  	default:
  3811  		s.setRunningCmd(false)
  3812  	}
  3813  
  3814  	// Stepping a single instruction will never require continuing again.
  3815  	if command == api.StepInstruction || command == api.ReverseStepInstruction {
  3816  		s.setRunningCmd(false)
  3817  	}
  3818  
  3819  	return state, err
  3820  }
  3821  
  3822  func (s *Session) handleLogPoints(state *api.DebuggerState) {
  3823  	for _, th := range state.Threads {
  3824  		if bp := th.Breakpoint; bp != nil {
  3825  			s.logBreakpointMessage(bp, th.GoroutineID)
  3826  		}
  3827  	}
  3828  }
  3829  
  3830  func (s *Session) stoppedGs(state *api.DebuggerState) (gs []int64) {
  3831  	// Check the current thread first. There may be no selected goroutine.
  3832  	if state.CurrentThread.Breakpoint != nil && !state.CurrentThread.Breakpoint.Tracepoint {
  3833  		gs = append(gs, state.CurrentThread.GoroutineID)
  3834  	}
  3835  	if s.debugger.StopReason() == proc.StopHardcodedBreakpoint {
  3836  		gs = append(gs, stoppedGoroutineID(state))
  3837  	}
  3838  	for _, th := range state.Threads {
  3839  		// Some threads may be stopped on a hardcoded breakpoint.
  3840  		// TODO(suzmue): This is a workaround for detecting hard coded breakpoints,
  3841  		// though this check is likely not sufficient. It would be better to resolve
  3842  		// this in the debugger layer instead.
  3843  		if th.Function.Name() == "runtime.breakpoint" {
  3844  			gs = append(gs, th.GoroutineID)
  3845  			continue
  3846  		}
  3847  		// We already added the current thread if it had a breakpoint.
  3848  		if th.ID == state.CurrentThread.ID {
  3849  			continue
  3850  		}
  3851  		if bp := th.Breakpoint; bp != nil {
  3852  			if !th.Breakpoint.Tracepoint {
  3853  				gs = append(gs, th.GoroutineID)
  3854  			}
  3855  		}
  3856  	}
  3857  	return gs
  3858  }
  3859  
  3860  func (s *Session) logBreakpointMessage(bp *api.Breakpoint, goid int64) bool {
  3861  	if !bp.Tracepoint {
  3862  		return false
  3863  	}
  3864  	if lMsg, ok := bp.UserData.(logMessage); ok {
  3865  		msg := lMsg.evaluate(s, goid)
  3866  		s.send(&dap.OutputEvent{
  3867  			Event: *newEvent("output"),
  3868  			Body: dap.OutputEventBody{
  3869  				Category: "stdout",
  3870  				Output:   fmt.Sprintf("> [Go %d]: %s\n", goid, msg),
  3871  				Source: &dap.Source{
  3872  					Path: s.toClientPath(bp.File),
  3873  				},
  3874  				Line: bp.Line,
  3875  			},
  3876  		})
  3877  	}
  3878  	return true
  3879  }
  3880  
  3881  func (msg *logMessage) evaluate(s *Session, goid int64) string {
  3882  	evaluated := make([]interface{}, len(msg.args))
  3883  	for i := range msg.args {
  3884  		exprVar, err := s.debugger.EvalVariableInScope(goid, 0, 0, msg.args[i], DefaultLoadConfig)
  3885  		if err != nil {
  3886  			evaluated[i] = fmt.Sprintf("{eval err: %e}", err)
  3887  			continue
  3888  		}
  3889  		evaluated[i], _ = s.convertVariableWithOpts(exprVar, "", skipRef|showFullValue)
  3890  	}
  3891  	return fmt.Sprintf(msg.format, evaluated...)
  3892  }
  3893  
  3894  func (s *Session) toClientPath(path string) string {
  3895  	if len(s.args.substitutePathServerToClient) == 0 {
  3896  		return path
  3897  	}
  3898  	clientPath := locspec.SubstitutePath(path, s.args.substitutePathServerToClient)
  3899  	if clientPath != path {
  3900  		s.config.log.Debugf("server path=%s converted to client path=%s\n", path, clientPath)
  3901  	}
  3902  	return clientPath
  3903  }
  3904  
  3905  func (s *Session) toServerPath(path string) string {
  3906  	if len(s.args.substitutePathClientToServer) == 0 {
  3907  		return path
  3908  	}
  3909  	serverPath := locspec.SubstitutePath(path, s.args.substitutePathClientToServer)
  3910  	if serverPath != path {
  3911  		s.config.log.Debugf("client path=%s converted to server path=%s\n", path, serverPath)
  3912  	}
  3913  	return serverPath
  3914  }
  3915  
  3916  type logMessage struct {
  3917  	format string
  3918  	args   []string
  3919  }
  3920  
  3921  // parseLogPoint parses a log message according to the DAP spec:
  3922  //
  3923  //	"Expressions within {} are interpolated."
  3924  func parseLogPoint(msg string) (bool, *logMessage, error) {
  3925  	// Note: All braces *must* come in pairs, even those within an
  3926  	// expression to be interpolated.
  3927  	// TODO(suzmue): support individual braces in string values in
  3928  	// eval expressions.
  3929  	var args []string
  3930  
  3931  	var isArg bool
  3932  	var formatSlice, argSlice []rune
  3933  	braceCount := 0
  3934  	for _, r := range msg {
  3935  		if isArg {
  3936  			switch r {
  3937  			case '}':
  3938  				if braceCount--; braceCount == 0 {
  3939  					argStr := strings.TrimSpace(string(argSlice))
  3940  					if len(argStr) == 0 {
  3941  						return false, nil, fmt.Errorf("empty evaluation string")
  3942  					}
  3943  					args = append(args, argStr)
  3944  					formatSlice = append(formatSlice, '%', 's')
  3945  					isArg = false
  3946  					continue
  3947  				}
  3948  			case '{':
  3949  				braceCount += 1
  3950  			}
  3951  			argSlice = append(argSlice, r)
  3952  			continue
  3953  		}
  3954  
  3955  		switch r {
  3956  		case '}':
  3957  			return false, nil, fmt.Errorf("invalid log point format, unexpected '}'")
  3958  		case '{':
  3959  			if braceCount++; braceCount == 1 {
  3960  				isArg, argSlice = true, []rune{}
  3961  				continue
  3962  			}
  3963  		}
  3964  		formatSlice = append(formatSlice, r)
  3965  	}
  3966  	if isArg {
  3967  		return false, nil, fmt.Errorf("invalid log point format")
  3968  	}
  3969  	if len(formatSlice) == 0 {
  3970  		return false, nil, nil
  3971  	}
  3972  	return true, &logMessage{
  3973  		format: string(formatSlice),
  3974  		args:   args,
  3975  	}, nil
  3976  }
  3977  
  3978  type syncflag struct {
  3979  	mu   sync.Mutex
  3980  	cond *sync.Cond
  3981  	flag bool
  3982  }
  3983  
  3984  func newSyncflag() *syncflag {
  3985  	r := &syncflag{
  3986  		flag: false,
  3987  	}
  3988  	r.cond = sync.NewCond(&r.mu)
  3989  	return r
  3990  }
  3991  
  3992  func (s *syncflag) wait() {
  3993  	s.mu.Lock()
  3994  	for !s.flag {
  3995  		s.cond.Wait()
  3996  	}
  3997  	s.mu.Unlock()
  3998  }
  3999  
  4000  func (s *syncflag) raise() {
  4001  	s.mu.Lock()
  4002  	s.flag = true
  4003  	s.mu.Unlock()
  4004  	s.cond.Broadcast()
  4005  }