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