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

     1  package debugger
     2  
     3  import (
     4  	"debug/dwarf"
     5  	"debug/elf"
     6  	"debug/macho"
     7  	"debug/pe"
     8  	"errors"
     9  	"fmt"
    10  	"go/parser"
    11  	"go/token"
    12  	"io"
    13  	"os"
    14  	"os/exec"
    15  	"path/filepath"
    16  	"regexp"
    17  	"runtime"
    18  	"sort"
    19  	"strconv"
    20  	"strings"
    21  	"sync"
    22  	"time"
    23  
    24  	"github.com/go-delve/delve/pkg/dwarf/op"
    25  	"github.com/go-delve/delve/pkg/gobuild"
    26  	"github.com/go-delve/delve/pkg/goversion"
    27  	"github.com/go-delve/delve/pkg/locspec"
    28  	"github.com/go-delve/delve/pkg/logflags"
    29  	"github.com/go-delve/delve/pkg/proc"
    30  	"github.com/go-delve/delve/pkg/proc/core"
    31  	"github.com/go-delve/delve/pkg/proc/gdbserial"
    32  	"github.com/go-delve/delve/pkg/proc/native"
    33  	"github.com/go-delve/delve/service/api"
    34  )
    35  
    36  var (
    37  	// ErrCanNotRestart is returned when the target cannot be restarted.
    38  	// This is returned for targets that have been attached to, or when
    39  	// debugging core files.
    40  	ErrCanNotRestart = errors.New("can not restart this target")
    41  
    42  	// ErrNotRecording is returned when StopRecording is called while the
    43  	// debugger is not recording the target.
    44  	ErrNotRecording = errors.New("debugger is not recording")
    45  
    46  	// ErrCoreDumpInProgress is returned when a core dump is already in progress.
    47  	ErrCoreDumpInProgress = errors.New("core dump in progress")
    48  
    49  	// ErrCoreDumpNotSupported is returned when core dumping is not supported
    50  	ErrCoreDumpNotSupported = errors.New("core dumping not supported")
    51  
    52  	// ErrNotImplementedWithMultitarget is returned for operations that are not implemented with multiple targets
    53  	ErrNotImplementedWithMultitarget = errors.New("not implemented for multiple targets")
    54  )
    55  
    56  // Debugger service.
    57  //
    58  // Debugger provides a higher level of
    59  // abstraction over proc.Process.
    60  // It handles converting from internal types to
    61  // the types expected by clients. It also handles
    62  // functionality needed by clients, but not needed in
    63  // lower lever packages such as proc.
    64  type Debugger struct {
    65  	config *Config
    66  	// arguments to launch a new process.
    67  	processArgs []string
    68  
    69  	targetMutex sync.Mutex
    70  	target      *proc.TargetGroup
    71  
    72  	log logflags.Logger
    73  
    74  	running      bool
    75  	runningMutex sync.Mutex
    76  
    77  	stopRecording func() error
    78  	recordMutex   sync.Mutex
    79  
    80  	dumpState proc.DumpState
    81  
    82  	breakpointIDCounter int
    83  }
    84  
    85  type ExecuteKind int
    86  
    87  const (
    88  	ExecutingExistingFile = ExecuteKind(iota)
    89  	ExecutingGeneratedFile
    90  	ExecutingGeneratedTest
    91  	ExecutingOther
    92  )
    93  
    94  // Config provides the configuration to start a Debugger.
    95  //
    96  // Only one of ProcessArgs or AttachPid should be specified. If ProcessArgs is
    97  // provided, a new process will be launched. Otherwise, the debugger will try
    98  // to attach to an existing process with AttachPid.
    99  type Config struct {
   100  	// WorkingDir is working directory of the new process. This field is used
   101  	// only when launching a new process.
   102  	WorkingDir string
   103  
   104  	// AttachPid is the PID of an existing process to which the debugger should
   105  	// attach.
   106  	AttachPid int
   107  	// If AttachWaitFor is set the debugger will wait for a process with a name
   108  	// starting with WaitFor and attach to it.
   109  	AttachWaitFor string
   110  	// AttachWaitForInterval is the time (in milliseconds) that the debugger
   111  	// waits between checks for WaitFor.
   112  	AttachWaitForInterval float64
   113  	// AttachWaitForDuration is the time (in milliseconds) that the debugger
   114  	// waits for WaitFor.
   115  	AttachWaitForDuration float64
   116  
   117  	// CoreFile specifies the path to the core dump to open.
   118  	CoreFile string
   119  
   120  	// Backend specifies the debugger backend.
   121  	Backend string
   122  
   123  	// Foreground lets target process access stdin.
   124  	Foreground bool
   125  
   126  	// DebugInfoDirectories is the list of directories to look for
   127  	// when resolving external debug info files.
   128  	DebugInfoDirectories []string
   129  
   130  	// CheckGoVersion is true if the debugger should check the version of Go
   131  	// used to compile the executable and refuse to work on incompatible
   132  	// versions.
   133  	CheckGoVersion bool
   134  
   135  	// TTY is passed along to the target process on creation. Used to specify a
   136  	// TTY for that process.
   137  	TTY string
   138  
   139  	// Packages contains the packages that we are debugging.
   140  	Packages []string
   141  
   142  	// BuildFlags contains the flags passed to the compiler.
   143  	BuildFlags string
   144  
   145  	// ExecuteKind contains the kind of the executed program.
   146  	ExecuteKind ExecuteKind
   147  
   148  	// Stdin Redirect file path for stdin
   149  	Stdin string
   150  
   151  	// Redirects specifies redirect rules for stdout
   152  	Stdout proc.OutputRedirect
   153  
   154  	// Redirects specifies redirect rules for stderr
   155  	Stderr proc.OutputRedirect
   156  
   157  	// DisableASLR disables ASLR
   158  	DisableASLR bool
   159  
   160  	RrOnProcessPid int
   161  }
   162  
   163  // New creates a new Debugger. ProcessArgs specify the commandline arguments for the
   164  // new process.
   165  func New(config *Config, processArgs []string) (*Debugger, error) {
   166  	logger := logflags.DebuggerLogger()
   167  	d := &Debugger{
   168  		config:      config,
   169  		processArgs: processArgs,
   170  		log:         logger,
   171  	}
   172  
   173  	// Create the process by either attaching or launching.
   174  	switch {
   175  	case d.config.AttachPid > 0 || d.config.AttachWaitFor != "":
   176  		d.log.Infof("attaching to pid %d", d.config.AttachPid)
   177  		path := ""
   178  		if len(d.processArgs) > 0 {
   179  			path = d.processArgs[0]
   180  		}
   181  		var waitFor *proc.WaitFor
   182  		if d.config.AttachWaitFor != "" {
   183  			waitFor = &proc.WaitFor{
   184  				Name:     d.config.AttachWaitFor,
   185  				Interval: time.Duration(d.config.AttachWaitForInterval * float64(time.Millisecond)),
   186  				Duration: time.Duration(d.config.AttachWaitForDuration * float64(time.Millisecond)),
   187  			}
   188  		}
   189  		var err error
   190  		d.target, err = d.Attach(d.config.AttachPid, path, waitFor)
   191  		if err != nil {
   192  			err = go11DecodeErrorCheck(err)
   193  			err = noDebugErrorWarning(err)
   194  			return nil, attachErrorMessage(d.config.AttachPid, err)
   195  		}
   196  
   197  	case d.config.CoreFile != "":
   198  		var err error
   199  		switch d.config.Backend {
   200  		case "rr":
   201  			d.log.Infof("opening trace %s", d.config.CoreFile)
   202  			d.target, err = gdbserial.Replay(d.config.CoreFile, false, false, d.config.DebugInfoDirectories, d.config.RrOnProcessPid, "")
   203  		default:
   204  			d.log.Infof("opening core file %s (executable %s)", d.config.CoreFile, d.processArgs[0])
   205  			d.target, err = core.OpenCore(d.config.CoreFile, d.processArgs[0], d.config.DebugInfoDirectories)
   206  		}
   207  		if err != nil {
   208  			err = go11DecodeErrorCheck(err)
   209  			return nil, err
   210  		}
   211  		if err := d.checkGoVersion(); err != nil {
   212  			d.target.Detach(true)
   213  			return nil, err
   214  		}
   215  
   216  	default:
   217  		d.log.Infof("launching process with args: %v", d.processArgs)
   218  		var err error
   219  		d.target, err = d.Launch(d.processArgs, d.config.WorkingDir)
   220  		if err != nil {
   221  			if _, ok := err.(*proc.ErrUnsupportedArch); !ok {
   222  				err = go11DecodeErrorCheck(err)
   223  				err = noDebugErrorWarning(err)
   224  				err = fmt.Errorf("could not launch process: %s", err)
   225  			}
   226  			return nil, err
   227  		}
   228  		if err := d.checkGoVersion(); err != nil {
   229  			d.target.Detach(true)
   230  			return nil, err
   231  		}
   232  	}
   233  
   234  	return d, nil
   235  }
   236  
   237  // canRestart returns true if the target was started with Launch and can be restarted
   238  func (d *Debugger) canRestart() bool {
   239  	switch {
   240  	case d.config.AttachPid > 0:
   241  		return false
   242  	case d.config.CoreFile != "":
   243  		return false
   244  	default:
   245  		return true
   246  	}
   247  }
   248  
   249  func (d *Debugger) checkGoVersion() error {
   250  	if d.isRecording() {
   251  		// do not do anything if we are still recording
   252  		return nil
   253  	}
   254  	producer := d.target.Selected.BinInfo().Producer()
   255  	if producer == "" {
   256  		return nil
   257  	}
   258  	return goversion.Compatible(producer, !d.config.CheckGoVersion)
   259  }
   260  
   261  func (d *Debugger) TargetGoVersion() string {
   262  	d.targetMutex.Lock()
   263  	defer d.targetMutex.Unlock()
   264  	return d.target.Selected.BinInfo().Producer()
   265  }
   266  
   267  // Launch will start a process with the given args and working directory.
   268  func (d *Debugger) Launch(processArgs []string, wd string) (*proc.TargetGroup, error) {
   269  	fullpath, err := verifyBinaryFormat(processArgs[0])
   270  	if err != nil {
   271  		return nil, err
   272  	}
   273  	processArgs[0] = fullpath
   274  
   275  	launchFlags := proc.LaunchFlags(0)
   276  	if d.config.Foreground {
   277  		launchFlags |= proc.LaunchForeground
   278  	}
   279  	if d.config.DisableASLR {
   280  		launchFlags |= proc.LaunchDisableASLR
   281  	}
   282  
   283  	switch d.config.Backend {
   284  	case "native":
   285  		return native.Launch(processArgs, wd, launchFlags, d.config.DebugInfoDirectories, d.config.TTY, d.config.Stdin, d.config.Stdout, d.config.Stderr)
   286  	case "lldb":
   287  		return betterGdbserialLaunchError(gdbserial.LLDBLaunch(processArgs, wd, launchFlags, d.config.DebugInfoDirectories, d.config.TTY, [3]string{d.config.Stdin, d.config.Stdout.Path, d.config.Stderr.Path}))
   288  	case "rr":
   289  		if d.target != nil {
   290  			// restart should not call us if the backend is 'rr'
   291  			panic("internal error: call to Launch with rr backend and target already exists")
   292  		}
   293  
   294  		run, stop, err := gdbserial.RecordAsync(processArgs, wd, false, d.config.Stdin, d.config.Stdout, d.config.Stderr)
   295  		if err != nil {
   296  			return nil, err
   297  		}
   298  
   299  		// let the initialization proceed but hold the targetMutex lock so that
   300  		// any other request to debugger will block except State(nowait=true) and
   301  		// Command(halt).
   302  		d.targetMutex.Lock()
   303  		d.recordingStart(stop)
   304  
   305  		go func() {
   306  			defer d.targetMutex.Unlock()
   307  
   308  			grp, err := d.recordingRun(run)
   309  			if err != nil {
   310  				d.log.Errorf("could not record target: %v", err)
   311  				// this is ugly but we can't respond to any client requests at this
   312  				// point so it's better if we die.
   313  				os.Exit(1)
   314  			}
   315  			d.recordingDone()
   316  			d.target = grp
   317  			if err := d.checkGoVersion(); err != nil {
   318  				d.log.Error(err)
   319  				err := d.target.Detach(true)
   320  				if err != nil {
   321  					d.log.Errorf("Error detaching from target: %v", err)
   322  				}
   323  			}
   324  		}()
   325  		return nil, nil
   326  
   327  	case "default":
   328  		if runtime.GOOS == "darwin" {
   329  			return betterGdbserialLaunchError(gdbserial.LLDBLaunch(processArgs, wd, launchFlags, d.config.DebugInfoDirectories, d.config.TTY, [3]string{d.config.Stdin, d.config.Stdout.Path, d.config.Stderr.Path}))
   330  		}
   331  		return native.Launch(processArgs, wd, launchFlags, d.config.DebugInfoDirectories, d.config.TTY, d.config.Stdin, d.config.Stdout, d.config.Stderr)
   332  	default:
   333  		return nil, fmt.Errorf("unknown backend %q", d.config.Backend)
   334  	}
   335  }
   336  
   337  func (d *Debugger) recordingStart(stop func() error) {
   338  	d.recordMutex.Lock()
   339  	d.stopRecording = stop
   340  	d.recordMutex.Unlock()
   341  }
   342  
   343  func (d *Debugger) recordingDone() {
   344  	d.recordMutex.Lock()
   345  	d.stopRecording = nil
   346  	d.recordMutex.Unlock()
   347  }
   348  
   349  func (d *Debugger) isRecording() bool {
   350  	d.recordMutex.Lock()
   351  	defer d.recordMutex.Unlock()
   352  	return d.stopRecording != nil
   353  }
   354  
   355  func (d *Debugger) recordingRun(run func() (string, error)) (*proc.TargetGroup, error) {
   356  	tracedir, err := run()
   357  	if err != nil && tracedir == "" {
   358  		return nil, err
   359  	}
   360  
   361  	return gdbserial.Replay(tracedir, false, true, d.config.DebugInfoDirectories, 0, strings.Join(d.processArgs, " "))
   362  }
   363  
   364  // Attach will attach to the process specified by 'pid'.
   365  func (d *Debugger) Attach(pid int, path string, waitFor *proc.WaitFor) (*proc.TargetGroup, error) {
   366  	switch d.config.Backend {
   367  	case "native":
   368  		return native.Attach(pid, waitFor, d.config.DebugInfoDirectories)
   369  	case "lldb":
   370  		return betterGdbserialLaunchError(gdbserial.LLDBAttach(pid, path, waitFor, d.config.DebugInfoDirectories))
   371  	case "default":
   372  		if runtime.GOOS == "darwin" {
   373  			return betterGdbserialLaunchError(gdbserial.LLDBAttach(pid, path, waitFor, d.config.DebugInfoDirectories))
   374  		}
   375  		return native.Attach(pid, waitFor, d.config.DebugInfoDirectories)
   376  	default:
   377  		return nil, fmt.Errorf("unknown backend %q", d.config.Backend)
   378  	}
   379  }
   380  
   381  var errMacOSBackendUnavailable = errors.New("debugserver or lldb-server not found: install Xcode's command line tools or lldb-server")
   382  
   383  func betterGdbserialLaunchError(p *proc.TargetGroup, err error) (*proc.TargetGroup, error) {
   384  	if runtime.GOOS != "darwin" {
   385  		return p, err
   386  	}
   387  	if _, isUnavailable := err.(*gdbserial.ErrBackendUnavailable); !isUnavailable {
   388  		return p, err
   389  	}
   390  
   391  	return p, errMacOSBackendUnavailable
   392  }
   393  
   394  // ProcessPid returns the PID of the process
   395  // the debugger is debugging.
   396  func (d *Debugger) ProcessPid() int {
   397  	d.targetMutex.Lock()
   398  	defer d.targetMutex.Unlock()
   399  	return d.target.Selected.Pid()
   400  }
   401  
   402  // LastModified returns the time that the process' executable was last
   403  // modified.
   404  func (d *Debugger) LastModified() time.Time {
   405  	d.targetMutex.Lock()
   406  	defer d.targetMutex.Unlock()
   407  	return d.target.Selected.BinInfo().LastModified()
   408  }
   409  
   410  // FunctionReturnLocations returns all return locations
   411  // for the given function, a list of addresses corresponding
   412  // to 'ret' or 'call runtime.deferreturn'.
   413  func (d *Debugger) FunctionReturnLocations(fnName string) ([]uint64, error) {
   414  	d.targetMutex.Lock()
   415  	defer d.targetMutex.Unlock()
   416  
   417  	if len(d.target.Targets()) > 1 {
   418  		return nil, ErrNotImplementedWithMultitarget
   419  	}
   420  
   421  	var (
   422  		p = d.target.Selected
   423  		g = p.SelectedGoroutine()
   424  	)
   425  
   426  	fns, err := p.BinInfo().FindFunction(fnName)
   427  	if err != nil {
   428  		return nil, err
   429  	}
   430  
   431  	var addrs []uint64
   432  
   433  	for _, fn := range fns {
   434  		var regs proc.Registers
   435  		mem := p.Memory()
   436  		if g != nil && g.Thread != nil {
   437  			regs, _ = g.Thread.Registers()
   438  		}
   439  		instructions, err := proc.Disassemble(mem, regs, p.Breakpoints(), p.BinInfo(), fn.Entry, fn.End)
   440  		if err != nil {
   441  			return nil, err
   442  		}
   443  
   444  		for _, instruction := range instructions {
   445  			if instruction.IsRet() {
   446  				addrs = append(addrs, instruction.Loc.PC)
   447  			}
   448  		}
   449  		addrs = append(addrs, proc.FindDeferReturnCalls(instructions)...)
   450  	}
   451  
   452  	return addrs, nil
   453  }
   454  
   455  // Detach detaches from the target process.
   456  // If `kill` is true we will kill the process after
   457  // detaching.
   458  func (d *Debugger) Detach(kill bool) error {
   459  	d.log.Debug("detaching")
   460  	d.targetMutex.Lock()
   461  	defer d.targetMutex.Unlock()
   462  	if ok, _ := d.target.Valid(); !ok {
   463  		return nil
   464  	}
   465  	return d.detach(kill)
   466  }
   467  
   468  func (d *Debugger) detach(kill bool) error {
   469  	if d.config.AttachPid == 0 {
   470  		kill = true
   471  	}
   472  	return d.target.Detach(kill)
   473  }
   474  
   475  // Restart will restart the target process, first killing
   476  // and then exec'ing it again.
   477  // If the target process is a recording it will restart it from the given
   478  // position. If pos starts with 'c' it's a checkpoint ID, otherwise it's an
   479  // event number. If resetArgs is true, newArgs will replace the process args.
   480  func (d *Debugger) Restart(rerecord bool, pos string, resetArgs bool, newArgs []string, newRedirects [3]string, rebuild bool) ([]api.DiscardedBreakpoint, error) {
   481  	d.targetMutex.Lock()
   482  	defer d.targetMutex.Unlock()
   483  
   484  	recorded, _ := d.target.Recorded()
   485  	if recorded && !rerecord {
   486  		d.target.ResumeNotify(nil)
   487  		return nil, d.target.Restart(pos)
   488  	}
   489  
   490  	if pos != "" {
   491  		return nil, proc.ErrNotRecorded
   492  	}
   493  
   494  	if !d.canRestart() {
   495  		return nil, ErrCanNotRestart
   496  	}
   497  
   498  	if !resetArgs && (d.config.Stdout.File != nil || d.config.Stderr.File != nil) {
   499  		return nil, ErrCanNotRestart
   500  
   501  	}
   502  
   503  	if err := d.detach(true); err != nil {
   504  		return nil, err
   505  	}
   506  	if resetArgs {
   507  		d.processArgs = append([]string{d.processArgs[0]}, newArgs...)
   508  		d.config.Stdin = newRedirects[0]
   509  		d.config.Stdout = proc.OutputRedirect{Path: newRedirects[1]}
   510  		d.config.Stderr = proc.OutputRedirect{Path: newRedirects[2]}
   511  	}
   512  	var grp *proc.TargetGroup
   513  	var err error
   514  
   515  	if rebuild {
   516  		switch d.config.ExecuteKind {
   517  		case ExecutingGeneratedFile:
   518  			err = gobuild.GoBuild(d.processArgs[0], d.config.Packages, d.config.BuildFlags)
   519  			if err != nil {
   520  				return nil, fmt.Errorf("could not rebuild process: %s", err)
   521  			}
   522  		case ExecutingGeneratedTest:
   523  			err = gobuild.GoTestBuild(d.processArgs[0], d.config.Packages, d.config.BuildFlags)
   524  			if err != nil {
   525  				return nil, fmt.Errorf("could not rebuild process: %s", err)
   526  			}
   527  		default:
   528  			// We cannot build a process that we didn't start, because we don't know how it was built.
   529  			return nil, fmt.Errorf("cannot rebuild a binary")
   530  		}
   531  	}
   532  
   533  	if recorded {
   534  		run, stop, err2 := gdbserial.RecordAsync(d.processArgs, d.config.WorkingDir, false, d.config.Stdin, d.config.Stdout, d.config.Stderr)
   535  		if err2 != nil {
   536  			return nil, err2
   537  		}
   538  
   539  		d.recordingStart(stop)
   540  		grp, err = d.recordingRun(run)
   541  		d.recordingDone()
   542  	} else {
   543  		grp, err = d.Launch(d.processArgs, d.config.WorkingDir)
   544  	}
   545  	if err != nil {
   546  		return nil, fmt.Errorf("could not launch process: %s", err)
   547  	}
   548  
   549  	discarded := []api.DiscardedBreakpoint{}
   550  	proc.Restart(grp, d.target, func(oldBp *proc.LogicalBreakpoint, err error) {
   551  		discarded = append(discarded, api.DiscardedBreakpoint{Breakpoint: api.ConvertLogicalBreakpoint(oldBp), Reason: err.Error()})
   552  	})
   553  	d.target = grp
   554  	return discarded, nil
   555  }
   556  
   557  // State returns the current state of the debugger.
   558  func (d *Debugger) State(nowait bool) (*api.DebuggerState, error) {
   559  	if d.IsRunning() && nowait {
   560  		return &api.DebuggerState{Running: true}, nil
   561  	}
   562  
   563  	if d.isRecording() && nowait {
   564  		return &api.DebuggerState{Recording: true}, nil
   565  	}
   566  
   567  	d.dumpState.Mutex.Lock()
   568  	if d.dumpState.Dumping && nowait {
   569  		return &api.DebuggerState{CoreDumping: true}, nil
   570  	}
   571  	d.dumpState.Mutex.Unlock()
   572  
   573  	d.targetMutex.Lock()
   574  	defer d.targetMutex.Unlock()
   575  	return d.state(nil, false)
   576  }
   577  
   578  func (d *Debugger) state(retLoadCfg *proc.LoadConfig, withBreakpointInfo bool) (*api.DebuggerState, error) {
   579  	if _, err := d.target.Valid(); err != nil {
   580  		return nil, err
   581  	}
   582  
   583  	var (
   584  		state     *api.DebuggerState
   585  		goroutine *api.Goroutine
   586  	)
   587  
   588  	tgt := d.target.Selected
   589  
   590  	if tgt.SelectedGoroutine() != nil {
   591  		goroutine = api.ConvertGoroutine(tgt, tgt.SelectedGoroutine())
   592  	}
   593  
   594  	exited := false
   595  	if _, err := tgt.Valid(); err != nil {
   596  		_, exited = err.(proc.ErrProcessExited)
   597  	}
   598  
   599  	state = &api.DebuggerState{
   600  		Pid:               tgt.Pid(),
   601  		TargetCommandLine: tgt.CmdLine,
   602  		SelectedGoroutine: goroutine,
   603  		Exited:            exited,
   604  	}
   605  
   606  	for _, thread := range d.target.ThreadList() {
   607  		th := api.ConvertThread(thread, d.ConvertThreadBreakpoint(thread))
   608  
   609  		th.CallReturn = thread.Common().CallReturn
   610  		if retLoadCfg != nil {
   611  			th.ReturnValues = api.ConvertVars(thread.Common().ReturnValues(*retLoadCfg))
   612  		}
   613  
   614  		if withBreakpointInfo {
   615  			err := d.collectBreakpointInformation(th, thread)
   616  			if err != nil {
   617  				return nil, err
   618  			}
   619  		}
   620  
   621  		state.Threads = append(state.Threads, th)
   622  		if thread.ThreadID() == tgt.CurrentThread().ThreadID() {
   623  			state.CurrentThread = th
   624  		}
   625  	}
   626  
   627  	state.NextInProgress = d.target.HasSteppingBreakpoints()
   628  
   629  	if recorded, _ := d.target.Recorded(); recorded {
   630  		state.When, _ = d.target.When()
   631  	}
   632  
   633  	t := proc.ValidTargets{Group: d.target}
   634  	for t.Next() {
   635  		for _, bp := range t.Breakpoints().WatchOutOfScope {
   636  			abp := api.ConvertLogicalBreakpoint(bp.Logical)
   637  			api.ConvertPhysicalBreakpoints(abp, bp.Logical, []int{t.Pid()}, []*proc.Breakpoint{bp})
   638  			state.WatchOutOfScope = append(state.WatchOutOfScope, abp)
   639  		}
   640  	}
   641  
   642  	return state, nil
   643  }
   644  
   645  // CreateBreakpoint creates a breakpoint using information from the provided `requestedBp`.
   646  // This function accepts several different ways of specifying where and how to create the
   647  // breakpoint that has been requested. Any error encountered during the attempt to set the
   648  // breakpoint will be returned to the caller.
   649  //
   650  // The ways of specifying a breakpoint are listed below in the order they are considered by
   651  // this function:
   652  //
   653  // - If requestedBp.TraceReturn is true then it is expected that
   654  // requestedBp.Addrs will contain the list of return addresses
   655  // supplied by the caller.
   656  //
   657  // - If requestedBp.File is not an empty string the breakpoint
   658  // will be created on the specified file:line location
   659  //
   660  // - If requestedBp.FunctionName is not an empty string
   661  // the breakpoint will be created on the specified function:line
   662  // location.
   663  //
   664  // - If requestedBp.Addrs is filled it will create a logical breakpoint
   665  // corresponding to all specified addresses.
   666  //
   667  // - Otherwise the value specified by arg.Breakpoint.Addr will be used.
   668  //
   669  // Note that this method will use the first successful method in order to
   670  // create a breakpoint, so mixing different fields will not result is multiple
   671  // breakpoints being set.
   672  //
   673  // If LocExpr is specified it will be used, along with substitutePathRules,
   674  // to re-enable the breakpoint after it is disabled.
   675  //
   676  // If suspended is true a logical breakpoint will be created even if the
   677  // location can not be found, the backend will attempt to enable the
   678  // breakpoint every time a new plugin is loaded.
   679  func (d *Debugger) CreateBreakpoint(requestedBp *api.Breakpoint, locExpr string, substitutePathRules [][2]string, suspended bool) (*api.Breakpoint, error) {
   680  	d.targetMutex.Lock()
   681  	defer d.targetMutex.Unlock()
   682  
   683  	var (
   684  		setbp proc.SetBreakpoint
   685  		err   error
   686  	)
   687  
   688  	if requestedBp.Name != "" {
   689  		if d.findBreakpointByName(requestedBp.Name) != nil {
   690  			return nil, errors.New("breakpoint name already exists")
   691  		}
   692  	}
   693  
   694  	if lbp := d.target.LogicalBreakpoints[requestedBp.ID]; lbp != nil {
   695  		abp := d.convertBreakpoint(lbp)
   696  		return abp, proc.BreakpointExistsError{File: lbp.File, Line: lbp.Line}
   697  	}
   698  
   699  	switch {
   700  	case requestedBp.TraceReturn:
   701  		if len(d.target.Targets()) != 1 {
   702  			return nil, ErrNotImplementedWithMultitarget
   703  		}
   704  		setbp.PidAddrs = []proc.PidAddr{{Pid: d.target.Selected.Pid(), Addr: requestedBp.Addr}}
   705  	case len(requestedBp.File) > 0:
   706  		fileName := requestedBp.File
   707  		if runtime.GOOS == "windows" {
   708  			// Accept fileName which is case-insensitive and slash-insensitive match
   709  			fileNameNormalized := strings.ToLower(filepath.ToSlash(fileName))
   710  			t := proc.ValidTargets{Group: d.target}
   711  		caseInsensitiveSearch:
   712  			for t.Next() {
   713  				for _, symFile := range t.BinInfo().Sources {
   714  					if fileNameNormalized == strings.ToLower(filepath.ToSlash(symFile)) {
   715  						fileName = symFile
   716  						break caseInsensitiveSearch
   717  					}
   718  				}
   719  			}
   720  		}
   721  		setbp.File = fileName
   722  		setbp.Line = requestedBp.Line
   723  	case len(requestedBp.FunctionName) > 0:
   724  		setbp.FunctionName = requestedBp.FunctionName
   725  		setbp.Line = requestedBp.Line
   726  	case len(requestedBp.Addrs) > 0:
   727  		setbp.PidAddrs = make([]proc.PidAddr, len(requestedBp.Addrs))
   728  		if len(d.target.Targets()) == 1 {
   729  			pid := d.target.Selected.Pid()
   730  			for i, addr := range requestedBp.Addrs {
   731  				setbp.PidAddrs[i] = proc.PidAddr{Pid: pid, Addr: addr}
   732  			}
   733  		} else {
   734  			if len(requestedBp.Addrs) != len(requestedBp.AddrPid) {
   735  				return nil, errors.New("mismatched length in addrs and addrpid")
   736  			}
   737  			for i, addr := range requestedBp.Addrs {
   738  				setbp.PidAddrs[i] = proc.PidAddr{Pid: requestedBp.AddrPid[i], Addr: addr}
   739  			}
   740  		}
   741  	default:
   742  		if requestedBp.Addr != 0 {
   743  			setbp.PidAddrs = []proc.PidAddr{{Pid: d.target.Selected.Pid(), Addr: requestedBp.Addr}}
   744  		}
   745  	}
   746  
   747  	if err != nil {
   748  		return nil, err
   749  	}
   750  
   751  	if locExpr != "" {
   752  		loc, err := locspec.Parse(locExpr)
   753  		if err != nil {
   754  			return nil, err
   755  		}
   756  		setbp.Expr = func(t *proc.Target) []uint64 {
   757  			locs, _, err := loc.Find(t, d.processArgs, nil, locExpr, false, substitutePathRules)
   758  			if err != nil || len(locs) != 1 {
   759  				logflags.DebuggerLogger().Debugf("could not evaluate breakpoint expression %q: %v (number of results %d)", locExpr, err, len(locs))
   760  				return nil
   761  			}
   762  			return locs[0].PCs
   763  		}
   764  		setbp.ExprString = locExpr
   765  	}
   766  
   767  	id := requestedBp.ID
   768  
   769  	if id <= 0 {
   770  		d.breakpointIDCounter++
   771  		id = d.breakpointIDCounter
   772  	} else {
   773  		d.breakpointIDCounter = id
   774  	}
   775  
   776  	lbp := &proc.LogicalBreakpoint{LogicalID: id, HitCount: make(map[int64]uint64), Enabled: true}
   777  	d.target.LogicalBreakpoints[id] = lbp
   778  
   779  	err = copyLogicalBreakpointInfo(lbp, requestedBp)
   780  	if err != nil {
   781  		return nil, err
   782  	}
   783  
   784  	lbp.Set = setbp
   785  
   786  	if lbp.Set.Expr != nil {
   787  		addrs := lbp.Set.Expr(d.Target())
   788  		if len(addrs) > 0 {
   789  			f, l, fn := d.Target().BinInfo().PCToLine(addrs[0])
   790  			lbp.File = f
   791  			lbp.Line = l
   792  			if fn != nil {
   793  				lbp.FunctionName = fn.Name
   794  			}
   795  		}
   796  	}
   797  
   798  	err = d.target.EnableBreakpoint(lbp)
   799  	if err != nil {
   800  		if suspended {
   801  			logflags.DebuggerLogger().Debugf("could not enable new breakpoint: %v (breakpoint will be suspended)", err)
   802  		} else {
   803  			delete(d.target.LogicalBreakpoints, lbp.LogicalID)
   804  			return nil, err
   805  		}
   806  	}
   807  
   808  	createdBp := d.convertBreakpoint(lbp)
   809  	d.log.Infof("created breakpoint: %#v", createdBp)
   810  	return createdBp, nil
   811  }
   812  
   813  func (d *Debugger) convertBreakpoint(lbp *proc.LogicalBreakpoint) *api.Breakpoint {
   814  	abp := api.ConvertLogicalBreakpoint(lbp)
   815  	bps := []*proc.Breakpoint{}
   816  	pids := []int{}
   817  	t := proc.ValidTargets{Group: d.target}
   818  	for t.Next() {
   819  		for _, bp := range t.Breakpoints().M {
   820  			if bp.LogicalID() == lbp.LogicalID {
   821  				bps = append(bps, bp)
   822  				pids = append(pids, t.Pid())
   823  			}
   824  		}
   825  	}
   826  	api.ConvertPhysicalBreakpoints(abp, lbp, pids, bps)
   827  	return abp
   828  }
   829  
   830  func (d *Debugger) ConvertThreadBreakpoint(thread proc.Thread) *api.Breakpoint {
   831  	if b := thread.Breakpoint(); b.Active && b.Breakpoint.Logical != nil {
   832  		return d.convertBreakpoint(b.Breakpoint.Logical)
   833  	}
   834  	return nil
   835  }
   836  
   837  func (d *Debugger) CreateEBPFTracepoint(fnName string) error {
   838  	d.targetMutex.Lock()
   839  	defer d.targetMutex.Unlock()
   840  	if len(d.target.Targets()) != 1 {
   841  		return ErrNotImplementedWithMultitarget
   842  	}
   843  	p := d.target.Selected
   844  	return p.SetEBPFTracepoint(fnName)
   845  }
   846  
   847  // amendBreakpoint will update the breakpoint with the matching ID.
   848  // It also enables or disables the breakpoint.
   849  // We can consume this function to avoid locking a goroutine.
   850  func (d *Debugger) amendBreakpoint(amend *api.Breakpoint) error {
   851  	original := d.target.LogicalBreakpoints[amend.ID]
   852  	if original == nil {
   853  		return fmt.Errorf("no breakpoint with ID %d", amend.ID)
   854  	}
   855  	enabledBefore := original.Enabled
   856  	err := copyLogicalBreakpointInfo(original, amend)
   857  	if err != nil {
   858  		return err
   859  	}
   860  	original.Enabled = !amend.Disabled
   861  
   862  	switch {
   863  	case enabledBefore && !original.Enabled:
   864  		if d.isWatchpoint(original) {
   865  			return errors.New("can not disable watchpoints")
   866  		}
   867  		err = d.target.DisableBreakpoint(original)
   868  	case !enabledBefore && original.Enabled:
   869  		err = d.target.EnableBreakpoint(original)
   870  	}
   871  	if err != nil {
   872  		return err
   873  	}
   874  
   875  	t := proc.ValidTargets{Group: d.target}
   876  	for t.Next() {
   877  		for _, bp := range t.Breakpoints().M {
   878  			if bp.LogicalID() == amend.ID {
   879  				bp.UserBreaklet().Cond = original.Cond
   880  			}
   881  		}
   882  	}
   883  	return nil
   884  }
   885  
   886  func (d *Debugger) isWatchpoint(lbp *proc.LogicalBreakpoint) bool {
   887  	t := proc.ValidTargets{Group: d.target}
   888  	for t.Next() {
   889  		for _, bp := range t.Breakpoints().M {
   890  			if bp.LogicalID() == lbp.LogicalID {
   891  				return bp.WatchType != 0
   892  			}
   893  		}
   894  	}
   895  	return false
   896  }
   897  
   898  // AmendBreakpoint will update the breakpoint with the matching ID.
   899  // It also enables or disables the breakpoint.
   900  func (d *Debugger) AmendBreakpoint(amend *api.Breakpoint) error {
   901  	d.targetMutex.Lock()
   902  	defer d.targetMutex.Unlock()
   903  
   904  	return d.amendBreakpoint(amend)
   905  }
   906  
   907  // CancelNext will clear internal breakpoints, thus cancelling the 'next',
   908  // 'step' or 'stepout' operation.
   909  func (d *Debugger) CancelNext() error {
   910  	d.targetMutex.Lock()
   911  	defer d.targetMutex.Unlock()
   912  	return d.target.ClearSteppingBreakpoints()
   913  }
   914  
   915  func copyLogicalBreakpointInfo(lbp *proc.LogicalBreakpoint, requested *api.Breakpoint) error {
   916  	lbp.Name = requested.Name
   917  	lbp.Tracepoint = requested.Tracepoint
   918  	lbp.TraceReturn = requested.TraceReturn
   919  	lbp.Goroutine = requested.Goroutine
   920  	lbp.Stacktrace = requested.Stacktrace
   921  	lbp.Variables = requested.Variables
   922  	lbp.LoadArgs = api.LoadConfigToProc(requested.LoadArgs)
   923  	lbp.LoadLocals = api.LoadConfigToProc(requested.LoadLocals)
   924  	lbp.UserData = requested.UserData
   925  	lbp.Cond = nil
   926  	if requested.Cond != "" {
   927  		var err error
   928  		lbp.Cond, err = parser.ParseExpr(requested.Cond)
   929  		if err != nil {
   930  			return err
   931  		}
   932  	}
   933  
   934  	lbp.HitCond = nil
   935  	if requested.HitCond != "" {
   936  		opTok, val, err := parseHitCondition(requested.HitCond)
   937  		if err != nil {
   938  			return err
   939  		}
   940  		lbp.HitCond = &struct {
   941  			Op  token.Token
   942  			Val int
   943  		}{opTok, val}
   944  		lbp.HitCondPerG = requested.HitCondPerG
   945  	}
   946  
   947  	return nil
   948  }
   949  
   950  func parseHitCondition(hitCond string) (token.Token, int, error) {
   951  	// A hit condition can be in the following formats:
   952  	// - "number"
   953  	// - "OP number"
   954  	hitConditionRegex := regexp.MustCompile(`((=|>|<|%|!)+|)( |)((\d|_)+)`)
   955  
   956  	match := hitConditionRegex.FindStringSubmatch(strings.TrimSpace(hitCond))
   957  	if match == nil || len(match) != 6 {
   958  		return 0, 0, fmt.Errorf("unable to parse breakpoint hit condition: %q\nhit conditions should be of the form \"number\" or \"OP number\"", hitCond)
   959  	}
   960  
   961  	opStr := match[1]
   962  	var opTok token.Token
   963  	switch opStr {
   964  	case "==", "":
   965  		opTok = token.EQL
   966  	case ">=":
   967  		opTok = token.GEQ
   968  	case "<=":
   969  		opTok = token.LEQ
   970  	case ">":
   971  		opTok = token.GTR
   972  	case "<":
   973  		opTok = token.LSS
   974  	case "%":
   975  		opTok = token.REM
   976  	case "!=":
   977  		opTok = token.NEQ
   978  	default:
   979  		return 0, 0, fmt.Errorf("unable to parse breakpoint hit condition: %q\ninvalid operator: %q", hitCond, opStr)
   980  	}
   981  
   982  	numStr := match[4]
   983  	val, parseErr := strconv.Atoi(numStr)
   984  	if parseErr != nil {
   985  		return 0, 0, fmt.Errorf("unable to parse breakpoint hit condition: %q\ninvalid number: %q", hitCond, numStr)
   986  	}
   987  
   988  	return opTok, val, nil
   989  }
   990  
   991  // ClearBreakpoint clears a breakpoint.
   992  func (d *Debugger) ClearBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoint, error) {
   993  	d.targetMutex.Lock()
   994  	defer d.targetMutex.Unlock()
   995  	if requestedBp.ID <= 0 {
   996  		if len(d.target.Targets()) != 1 {
   997  			return nil, ErrNotImplementedWithMultitarget
   998  		}
   999  		bp := d.target.Selected.Breakpoints().M[requestedBp.Addr]
  1000  		requestedBp.ID = bp.LogicalID()
  1001  	}
  1002  
  1003  	lbp := d.target.LogicalBreakpoints[requestedBp.ID]
  1004  	clearedBp := d.convertBreakpoint(lbp)
  1005  
  1006  	err := d.target.DisableBreakpoint(lbp)
  1007  	if err != nil {
  1008  		return nil, err
  1009  	}
  1010  
  1011  	delete(d.target.LogicalBreakpoints, requestedBp.ID)
  1012  
  1013  	d.log.Infof("cleared breakpoint: %#v", clearedBp)
  1014  	return clearedBp, nil
  1015  }
  1016  
  1017  // isBpHitCondNotSatisfiable returns true if the breakpoint bp has a hit
  1018  // condition that is no more satisfiable.
  1019  // The hit condition is considered no more satisfiable if it can no longer be
  1020  // hit again, for example with {Op: "==", Val: 1} and TotalHitCount == 1.
  1021  func isBpHitCondNotSatisfiable(bp *api.Breakpoint) bool {
  1022  	if bp.HitCond == "" {
  1023  		return false
  1024  	}
  1025  
  1026  	tok, val, err := parseHitCondition(bp.HitCond)
  1027  	if err != nil {
  1028  		return false
  1029  	}
  1030  	switch tok {
  1031  	case token.EQL, token.LEQ:
  1032  		if int(bp.TotalHitCount) >= val {
  1033  			return true
  1034  		}
  1035  	case token.LSS:
  1036  		if int(bp.TotalHitCount) >= val-1 {
  1037  			return true
  1038  		}
  1039  	}
  1040  
  1041  	return false
  1042  }
  1043  
  1044  // Breakpoints returns the list of current breakpoints.
  1045  func (d *Debugger) Breakpoints(all bool) []*api.Breakpoint {
  1046  	d.targetMutex.Lock()
  1047  	defer d.targetMutex.Unlock()
  1048  
  1049  	abps := []*api.Breakpoint{}
  1050  	if all {
  1051  		t := proc.ValidTargets{Group: d.target}
  1052  		for t.Next() {
  1053  			for _, bp := range t.Breakpoints().M {
  1054  				var abp *api.Breakpoint
  1055  				if bp.Logical != nil {
  1056  					abp = api.ConvertLogicalBreakpoint(bp.Logical)
  1057  				} else {
  1058  					abp = &api.Breakpoint{}
  1059  				}
  1060  				api.ConvertPhysicalBreakpoints(abp, bp.Logical, []int{t.Pid()}, []*proc.Breakpoint{bp})
  1061  				abp.VerboseDescr = bp.VerboseDescr()
  1062  				abps = append(abps, abp)
  1063  			}
  1064  		}
  1065  	} else {
  1066  		for _, lbp := range d.target.LogicalBreakpoints {
  1067  			abps = append(abps, d.convertBreakpoint(lbp))
  1068  		}
  1069  	}
  1070  	return abps
  1071  }
  1072  
  1073  // FindBreakpoint returns the breakpoint specified by 'id'.
  1074  func (d *Debugger) FindBreakpoint(id int) *api.Breakpoint {
  1075  	d.targetMutex.Lock()
  1076  	defer d.targetMutex.Unlock()
  1077  	lbp := d.target.LogicalBreakpoints[id]
  1078  	if lbp == nil {
  1079  		return nil
  1080  	}
  1081  	return d.convertBreakpoint(lbp)
  1082  }
  1083  
  1084  // FindBreakpointByName returns the breakpoint specified by 'name'
  1085  func (d *Debugger) FindBreakpointByName(name string) *api.Breakpoint {
  1086  	d.targetMutex.Lock()
  1087  	defer d.targetMutex.Unlock()
  1088  	return d.findBreakpointByName(name)
  1089  }
  1090  
  1091  func (d *Debugger) findBreakpointByName(name string) *api.Breakpoint {
  1092  	for _, lbp := range d.target.LogicalBreakpoints {
  1093  		if lbp.Name == name {
  1094  			return d.convertBreakpoint(lbp)
  1095  		}
  1096  	}
  1097  	return nil
  1098  }
  1099  
  1100  // CreateWatchpoint creates a watchpoint on the specified expression.
  1101  func (d *Debugger) CreateWatchpoint(goid int64, frame, deferredCall int, expr string, wtype api.WatchType) (*api.Breakpoint, error) {
  1102  	p := d.target.Selected
  1103  
  1104  	s, err := proc.ConvertEvalScope(p, goid, frame, deferredCall)
  1105  	if err != nil {
  1106  		return nil, err
  1107  	}
  1108  	d.breakpointIDCounter++
  1109  	bp, err := p.SetWatchpoint(d.breakpointIDCounter, s, expr, proc.WatchType(wtype), nil)
  1110  	if err != nil {
  1111  		return nil, err
  1112  	}
  1113  	if d.findBreakpointByName(expr) == nil {
  1114  		bp.Logical.Name = expr
  1115  	}
  1116  	return d.convertBreakpoint(bp.Logical), nil
  1117  }
  1118  
  1119  // Threads returns the threads of the target process.
  1120  func (d *Debugger) Threads() ([]proc.Thread, error) {
  1121  	d.targetMutex.Lock()
  1122  	defer d.targetMutex.Unlock()
  1123  
  1124  	if _, err := d.target.Valid(); err != nil {
  1125  		return nil, err
  1126  	}
  1127  
  1128  	return d.target.ThreadList(), nil
  1129  }
  1130  
  1131  // FindThread returns the thread for the given 'id'.
  1132  func (d *Debugger) FindThread(id int) (proc.Thread, error) {
  1133  	d.targetMutex.Lock()
  1134  	defer d.targetMutex.Unlock()
  1135  
  1136  	if _, err := d.target.Valid(); err != nil {
  1137  		return nil, err
  1138  	}
  1139  
  1140  	for _, th := range d.target.ThreadList() {
  1141  		if th.ThreadID() == id {
  1142  			return th, nil
  1143  		}
  1144  	}
  1145  	return nil, nil
  1146  }
  1147  
  1148  // FindGoroutine returns the goroutine for the given 'id'.
  1149  func (d *Debugger) FindGoroutine(id int64) (*proc.G, error) {
  1150  	d.targetMutex.Lock()
  1151  	defer d.targetMutex.Unlock()
  1152  
  1153  	return proc.FindGoroutine(d.target.Selected, id)
  1154  }
  1155  
  1156  func (d *Debugger) setRunning(running bool) {
  1157  	d.runningMutex.Lock()
  1158  	d.running = running
  1159  	d.runningMutex.Unlock()
  1160  }
  1161  
  1162  func (d *Debugger) IsRunning() bool {
  1163  	d.runningMutex.Lock()
  1164  	defer d.runningMutex.Unlock()
  1165  	return d.running
  1166  }
  1167  
  1168  // Command handles commands which control the debugger lifecycle
  1169  func (d *Debugger) Command(command *api.DebuggerCommand, resumeNotify chan struct{}) (*api.DebuggerState, error) {
  1170  	var err error
  1171  
  1172  	if command.Name == api.Halt {
  1173  		// RequestManualStop does not invoke any ptrace syscalls, so it's safe to
  1174  		// access the process directly.
  1175  		d.log.Debug("halting")
  1176  
  1177  		d.recordMutex.Lock()
  1178  		if d.stopRecording == nil {
  1179  			err = d.target.RequestManualStop()
  1180  			// The error returned from d.target.Valid will have more context
  1181  			// about the exited process.
  1182  			if _, valErr := d.target.Valid(); valErr != nil {
  1183  				err = valErr
  1184  			}
  1185  		}
  1186  		d.recordMutex.Unlock()
  1187  	}
  1188  
  1189  	withBreakpointInfo := true
  1190  
  1191  	d.targetMutex.Lock()
  1192  	defer d.targetMutex.Unlock()
  1193  
  1194  	d.setRunning(true)
  1195  	defer d.setRunning(false)
  1196  
  1197  	if command.Name != api.SwitchGoroutine && command.Name != api.SwitchThread && command.Name != api.Halt {
  1198  		d.target.ResumeNotify(resumeNotify)
  1199  	} else if resumeNotify != nil {
  1200  		close(resumeNotify)
  1201  	}
  1202  
  1203  	switch command.Name {
  1204  	case api.Continue:
  1205  		d.log.Debug("continuing")
  1206  		if err := d.target.ChangeDirection(proc.Forward); err != nil {
  1207  			return nil, err
  1208  		}
  1209  		err = d.target.Continue()
  1210  	case api.DirectionCongruentContinue:
  1211  		d.log.Debug("continuing (direction congruent)")
  1212  		err = d.target.Continue()
  1213  	case api.Call:
  1214  		d.log.Debugf("function call %s", command.Expr)
  1215  		if err := d.target.ChangeDirection(proc.Forward); err != nil {
  1216  			return nil, err
  1217  		}
  1218  		if command.ReturnInfoLoadConfig == nil {
  1219  			return nil, errors.New("can not call function with nil ReturnInfoLoadConfig")
  1220  		}
  1221  		g := d.target.Selected.SelectedGoroutine()
  1222  		if command.GoroutineID > 0 {
  1223  			g, err = proc.FindGoroutine(d.target.Selected, command.GoroutineID)
  1224  			if err != nil {
  1225  				return nil, err
  1226  			}
  1227  		}
  1228  		err = proc.EvalExpressionWithCalls(d.target, g, command.Expr, *api.LoadConfigToProc(command.ReturnInfoLoadConfig), !command.UnsafeCall)
  1229  	case api.Rewind:
  1230  		d.log.Debug("rewinding")
  1231  		if err := d.target.ChangeDirection(proc.Backward); err != nil {
  1232  			return nil, err
  1233  		}
  1234  		err = d.target.Continue()
  1235  	case api.Next:
  1236  		d.log.Debug("nexting")
  1237  		if err := d.target.ChangeDirection(proc.Forward); err != nil {
  1238  			return nil, err
  1239  		}
  1240  		err = d.target.Next()
  1241  	case api.ReverseNext:
  1242  		d.log.Debug("reverse nexting")
  1243  		if err := d.target.ChangeDirection(proc.Backward); err != nil {
  1244  			return nil, err
  1245  		}
  1246  		err = d.target.Next()
  1247  	case api.Step:
  1248  		d.log.Debug("stepping")
  1249  		if err := d.target.ChangeDirection(proc.Forward); err != nil {
  1250  			return nil, err
  1251  		}
  1252  		err = d.target.Step()
  1253  	case api.ReverseStep:
  1254  		d.log.Debug("reverse stepping")
  1255  		if err := d.target.ChangeDirection(proc.Backward); err != nil {
  1256  			return nil, err
  1257  		}
  1258  		err = d.target.Step()
  1259  	case api.StepInstruction:
  1260  		d.log.Debug("single stepping")
  1261  		if err := d.target.ChangeDirection(proc.Forward); err != nil {
  1262  			return nil, err
  1263  		}
  1264  		err = d.target.StepInstruction()
  1265  	case api.ReverseStepInstruction:
  1266  		d.log.Debug("reverse single stepping")
  1267  		if err := d.target.ChangeDirection(proc.Backward); err != nil {
  1268  			return nil, err
  1269  		}
  1270  		err = d.target.StepInstruction()
  1271  	case api.StepOut:
  1272  		d.log.Debug("step out")
  1273  		if err := d.target.ChangeDirection(proc.Forward); err != nil {
  1274  			return nil, err
  1275  		}
  1276  		err = d.target.StepOut()
  1277  	case api.ReverseStepOut:
  1278  		d.log.Debug("reverse step out")
  1279  		if err := d.target.ChangeDirection(proc.Backward); err != nil {
  1280  			return nil, err
  1281  		}
  1282  		err = d.target.StepOut()
  1283  	case api.SwitchThread:
  1284  		d.log.Debugf("switching to thread %d", command.ThreadID)
  1285  		t := proc.ValidTargets{Group: d.target}
  1286  		for t.Next() {
  1287  			if _, ok := t.FindThread(command.ThreadID); ok {
  1288  				d.target.Selected = t.Target
  1289  				break
  1290  			}
  1291  		}
  1292  		err = d.target.Selected.SwitchThread(command.ThreadID)
  1293  		withBreakpointInfo = false
  1294  	case api.SwitchGoroutine:
  1295  		d.log.Debugf("switching to goroutine %d", command.GoroutineID)
  1296  		var g *proc.G
  1297  		g, err = proc.FindGoroutine(d.target.Selected, command.GoroutineID)
  1298  		if err == nil {
  1299  			err = d.target.Selected.SwitchGoroutine(g)
  1300  		}
  1301  		withBreakpointInfo = false
  1302  	case api.Halt:
  1303  		// RequestManualStop already called
  1304  		withBreakpointInfo = false
  1305  	}
  1306  
  1307  	if err != nil {
  1308  		if pe, ok := err.(proc.ErrProcessExited); ok && command.Name != api.SwitchGoroutine && command.Name != api.SwitchThread {
  1309  			state := &api.DebuggerState{}
  1310  			state.Pid = d.target.Selected.Pid()
  1311  			state.Exited = true
  1312  			state.ExitStatus = pe.Status
  1313  			state.Err = pe
  1314  			return state, nil
  1315  		}
  1316  		return nil, err
  1317  	}
  1318  	state, stateErr := d.state(api.LoadConfigToProc(command.ReturnInfoLoadConfig), withBreakpointInfo)
  1319  	if stateErr != nil {
  1320  		return state, stateErr
  1321  	}
  1322  	for _, th := range state.Threads {
  1323  		if th.Breakpoint != nil && th.Breakpoint.TraceReturn {
  1324  			for _, v := range th.BreakpointInfo.Arguments {
  1325  				if (v.Flags & api.VariableReturnArgument) != 0 {
  1326  					th.ReturnValues = append(th.ReturnValues, v)
  1327  				}
  1328  			}
  1329  		}
  1330  	}
  1331  	if bp := state.CurrentThread.Breakpoint; bp != nil && isBpHitCondNotSatisfiable(bp) {
  1332  		bp.Disabled = true
  1333  		d.amendBreakpoint(bp)
  1334  	}
  1335  	return state, err
  1336  }
  1337  
  1338  func (d *Debugger) collectBreakpointInformation(apiThread *api.Thread, thread proc.Thread) error {
  1339  	if apiThread.Breakpoint == nil || apiThread.BreakpointInfo != nil {
  1340  		return nil
  1341  	}
  1342  
  1343  	bp := apiThread.Breakpoint
  1344  	bpi := &api.BreakpointInfo{}
  1345  	apiThread.BreakpointInfo = bpi
  1346  
  1347  	tgt := d.target.TargetForThread(thread.ThreadID())
  1348  
  1349  	// If we're dealing with a stripped binary don't attempt to load more
  1350  	// information, we won't be able to.
  1351  	img := tgt.BinInfo().PCToImage(bp.Addr)
  1352  	if img != nil && img.Stripped() {
  1353  		return nil
  1354  	}
  1355  
  1356  	if bp.Goroutine {
  1357  		g, err := proc.GetG(thread)
  1358  		if err != nil {
  1359  			return err
  1360  		}
  1361  		bpi.Goroutine = api.ConvertGoroutine(tgt, g)
  1362  	}
  1363  
  1364  	if bp.Stacktrace > 0 {
  1365  		rawlocs, err := proc.ThreadStacktrace(tgt, thread, bp.Stacktrace)
  1366  		if err != nil {
  1367  			return err
  1368  		}
  1369  		bpi.Stacktrace, err = d.convertStacktrace(rawlocs, nil)
  1370  		if err != nil {
  1371  			return err
  1372  		}
  1373  	}
  1374  
  1375  	if len(bp.Variables) == 0 && bp.LoadArgs == nil && bp.LoadLocals == nil {
  1376  		// don't try to create goroutine scope if there is nothing to load
  1377  		return nil
  1378  	}
  1379  
  1380  	s, err := proc.GoroutineScope(tgt, thread)
  1381  	if err != nil {
  1382  		return err
  1383  	}
  1384  
  1385  	if len(bp.Variables) > 0 {
  1386  		bpi.Variables = make([]api.Variable, len(bp.Variables))
  1387  	}
  1388  	for i := range bp.Variables {
  1389  		v, err := s.EvalExpression(bp.Variables[i], proc.LoadConfig{FollowPointers: true, MaxVariableRecurse: 1, MaxStringLen: 64, MaxArrayValues: 64, MaxStructFields: -1})
  1390  		if err != nil {
  1391  			bpi.Variables[i] = api.Variable{Name: bp.Variables[i], Unreadable: fmt.Sprintf("eval error: %v", err)}
  1392  		} else {
  1393  			bpi.Variables[i] = *api.ConvertVar(v)
  1394  		}
  1395  	}
  1396  	if bp.LoadArgs != nil {
  1397  		if vars, err := s.FunctionArguments(*api.LoadConfigToProc(bp.LoadArgs)); err == nil {
  1398  			bpi.Arguments = api.ConvertVars(vars)
  1399  		}
  1400  	}
  1401  	if bp.LoadLocals != nil {
  1402  		if locals, err := s.LocalVariables(*api.LoadConfigToProc(bp.LoadLocals)); err == nil {
  1403  			bpi.Locals = api.ConvertVars(locals)
  1404  		}
  1405  	}
  1406  	return nil
  1407  }
  1408  
  1409  // Sources returns a list of the source files for target binary.
  1410  func (d *Debugger) Sources(filter string) ([]string, error) {
  1411  	d.targetMutex.Lock()
  1412  	defer d.targetMutex.Unlock()
  1413  
  1414  	regex, err := regexp.Compile(filter)
  1415  	if err != nil {
  1416  		return nil, fmt.Errorf("invalid filter argument: %s", err.Error())
  1417  	}
  1418  
  1419  	files := []string{}
  1420  	t := proc.ValidTargets{Group: d.target}
  1421  	for t.Next() {
  1422  		for _, f := range t.BinInfo().Sources {
  1423  			if regex.MatchString(f) {
  1424  				files = append(files, f)
  1425  			}
  1426  		}
  1427  	}
  1428  	sort.Strings(files)
  1429  	files = uniq(files)
  1430  	return files, nil
  1431  }
  1432  
  1433  func uniq(s []string) []string {
  1434  	if len(s) == 0 {
  1435  		return s
  1436  	}
  1437  	src, dst := 1, 1
  1438  	for src < len(s) {
  1439  		if s[src] != s[dst-1] {
  1440  			s[dst] = s[src]
  1441  			dst++
  1442  		}
  1443  		src++
  1444  	}
  1445  	return s[:dst]
  1446  }
  1447  
  1448  // Functions returns a list of functions in the target process.
  1449  func (d *Debugger) Functions(filter string) ([]string, error) {
  1450  	d.targetMutex.Lock()
  1451  	defer d.targetMutex.Unlock()
  1452  
  1453  	regex, err := regexp.Compile(filter)
  1454  	if err != nil {
  1455  		return nil, fmt.Errorf("invalid filter argument: %s", err.Error())
  1456  	}
  1457  
  1458  	funcs := []string{}
  1459  	t := proc.ValidTargets{Group: d.target}
  1460  	for t.Next() {
  1461  		for _, f := range t.BinInfo().Functions {
  1462  			if regex.MatchString(f.Name) {
  1463  				funcs = append(funcs, f.Name)
  1464  			}
  1465  		}
  1466  	}
  1467  	sort.Strings(funcs)
  1468  	funcs = uniq(funcs)
  1469  	return funcs, nil
  1470  }
  1471  
  1472  // Types returns all type information in the binary.
  1473  func (d *Debugger) Types(filter string) ([]string, error) {
  1474  	d.targetMutex.Lock()
  1475  	defer d.targetMutex.Unlock()
  1476  
  1477  	regex, err := regexp.Compile(filter)
  1478  	if err != nil {
  1479  		return nil, fmt.Errorf("invalid filter argument: %s", err.Error())
  1480  	}
  1481  
  1482  	r := []string{}
  1483  
  1484  	t := proc.ValidTargets{Group: d.target}
  1485  	for t.Next() {
  1486  		types, err := t.BinInfo().Types()
  1487  		if err != nil {
  1488  			return nil, err
  1489  		}
  1490  
  1491  		for _, typ := range types {
  1492  			if regex.MatchString(typ) {
  1493  				r = append(r, typ)
  1494  			}
  1495  		}
  1496  	}
  1497  	sort.Strings(r)
  1498  	r = uniq(r)
  1499  
  1500  	return r, nil
  1501  }
  1502  
  1503  // PackageVariables returns a list of package variables for the thread,
  1504  // optionally regexp filtered using regexp described in 'filter'.
  1505  func (d *Debugger) PackageVariables(filter string, cfg proc.LoadConfig) ([]*proc.Variable, error) {
  1506  	d.targetMutex.Lock()
  1507  	defer d.targetMutex.Unlock()
  1508  	p := d.target.Selected
  1509  
  1510  	regex, err := regexp.Compile(filter)
  1511  	if err != nil {
  1512  		return nil, fmt.Errorf("invalid filter argument: %s", err.Error())
  1513  	}
  1514  
  1515  	scope, err := proc.ThreadScope(p, p.CurrentThread())
  1516  	if err != nil {
  1517  		return nil, err
  1518  	}
  1519  	pv, err := scope.PackageVariables(cfg)
  1520  	if err != nil {
  1521  		return nil, err
  1522  	}
  1523  	pvr := pv[:0]
  1524  	for i := range pv {
  1525  		if regex.MatchString(pv[i].Name) {
  1526  			pvr = append(pvr, pv[i])
  1527  		}
  1528  	}
  1529  	return pvr, nil
  1530  }
  1531  
  1532  // ThreadRegisters returns registers of the specified thread.
  1533  func (d *Debugger) ThreadRegisters(threadID int, floatingPoint bool) (*op.DwarfRegisters, error) {
  1534  	d.targetMutex.Lock()
  1535  	defer d.targetMutex.Unlock()
  1536  
  1537  	thread, found := d.target.Selected.FindThread(threadID)
  1538  	if !found {
  1539  		return nil, fmt.Errorf("couldn't find thread %d", threadID)
  1540  	}
  1541  	regs, err := thread.Registers()
  1542  	if err != nil {
  1543  		return nil, err
  1544  	}
  1545  	return d.target.Selected.BinInfo().Arch.RegistersToDwarfRegisters(0, regs), nil
  1546  }
  1547  
  1548  // ScopeRegisters returns registers for the specified scope.
  1549  func (d *Debugger) ScopeRegisters(goid int64, frame, deferredCall int, floatingPoint bool) (*op.DwarfRegisters, error) {
  1550  	d.targetMutex.Lock()
  1551  	defer d.targetMutex.Unlock()
  1552  
  1553  	s, err := proc.ConvertEvalScope(d.target.Selected, goid, frame, deferredCall)
  1554  	if err != nil {
  1555  		return nil, err
  1556  	}
  1557  	return &s.Regs, nil
  1558  }
  1559  
  1560  // DwarfRegisterToString returns the name and value representation of the given register.
  1561  func (d *Debugger) DwarfRegisterToString(i int, reg *op.DwarfRegister) (string, bool, string) {
  1562  	return d.target.Selected.BinInfo().Arch.DwarfRegisterToString(i, reg)
  1563  }
  1564  
  1565  // LocalVariables returns a list of the local variables.
  1566  func (d *Debugger) LocalVariables(goid int64, frame, deferredCall int, cfg proc.LoadConfig) ([]*proc.Variable, error) {
  1567  	d.targetMutex.Lock()
  1568  	defer d.targetMutex.Unlock()
  1569  
  1570  	s, err := proc.ConvertEvalScope(d.target.Selected, goid, frame, deferredCall)
  1571  	if err != nil {
  1572  		return nil, err
  1573  	}
  1574  	return s.LocalVariables(cfg)
  1575  }
  1576  
  1577  // FunctionArguments returns the arguments to the current function.
  1578  func (d *Debugger) FunctionArguments(goid int64, frame, deferredCall int, cfg proc.LoadConfig) ([]*proc.Variable, error) {
  1579  	d.targetMutex.Lock()
  1580  	defer d.targetMutex.Unlock()
  1581  
  1582  	s, err := proc.ConvertEvalScope(d.target.Selected, goid, frame, deferredCall)
  1583  	if err != nil {
  1584  		return nil, err
  1585  	}
  1586  	return s.FunctionArguments(cfg)
  1587  }
  1588  
  1589  // Function returns the current function.
  1590  func (d *Debugger) Function(goid int64, frame, deferredCall int, cfg proc.LoadConfig) (*proc.Function, error) {
  1591  	d.targetMutex.Lock()
  1592  	defer d.targetMutex.Unlock()
  1593  
  1594  	s, err := proc.ConvertEvalScope(d.target.Selected, goid, frame, deferredCall)
  1595  	if err != nil {
  1596  		return nil, err
  1597  	}
  1598  	return s.Fn, nil
  1599  }
  1600  
  1601  // EvalVariableInScope will attempt to evaluate the 'expr' in the scope
  1602  // corresponding to the given 'frame' on the goroutine identified by 'goid'.
  1603  func (d *Debugger) EvalVariableInScope(goid int64, frame, deferredCall int, expr string, cfg proc.LoadConfig) (*proc.Variable, error) {
  1604  	d.targetMutex.Lock()
  1605  	defer d.targetMutex.Unlock()
  1606  
  1607  	s, err := proc.ConvertEvalScope(d.target.Selected, goid, frame, deferredCall)
  1608  	if err != nil {
  1609  		return nil, err
  1610  	}
  1611  	return s.EvalExpression(expr, cfg)
  1612  }
  1613  
  1614  // LoadResliced will attempt to 'reslice' a map, array or slice so that the values
  1615  // up to cfg.MaxArrayValues children are loaded starting from index start.
  1616  func (d *Debugger) LoadResliced(v *proc.Variable, start int, cfg proc.LoadConfig) (*proc.Variable, error) {
  1617  	d.targetMutex.Lock()
  1618  	defer d.targetMutex.Unlock()
  1619  	return v.LoadResliced(start, cfg)
  1620  }
  1621  
  1622  // SetVariableInScope will set the value of the variable represented by
  1623  // 'symbol' to the value given, in the given scope.
  1624  func (d *Debugger) SetVariableInScope(goid int64, frame, deferredCall int, symbol, value string) error {
  1625  	d.targetMutex.Lock()
  1626  	defer d.targetMutex.Unlock()
  1627  
  1628  	s, err := proc.ConvertEvalScope(d.target.Selected, goid, frame, deferredCall)
  1629  	if err != nil {
  1630  		return err
  1631  	}
  1632  	return s.SetVariable(symbol, value)
  1633  }
  1634  
  1635  // Goroutines will return a list of goroutines in the target process.
  1636  func (d *Debugger) Goroutines(start, count int) ([]*proc.G, int, error) {
  1637  	d.targetMutex.Lock()
  1638  	defer d.targetMutex.Unlock()
  1639  	return proc.GoroutinesInfo(d.target.Selected, start, count)
  1640  }
  1641  
  1642  // FilterGoroutines returns the goroutines in gs that satisfy the specified filters.
  1643  func (d *Debugger) FilterGoroutines(gs []*proc.G, filters []api.ListGoroutinesFilter) []*proc.G {
  1644  	if len(filters) == 0 {
  1645  		return gs
  1646  	}
  1647  	d.targetMutex.Lock()
  1648  	defer d.targetMutex.Unlock()
  1649  	r := []*proc.G{}
  1650  	for _, g := range gs {
  1651  		ok := true
  1652  		for i := range filters {
  1653  			if !matchGoroutineFilter(d.target.Selected, g, &filters[i]) {
  1654  				ok = false
  1655  				break
  1656  			}
  1657  		}
  1658  		if ok {
  1659  			r = append(r, g)
  1660  		}
  1661  	}
  1662  	return r
  1663  }
  1664  
  1665  func matchGoroutineFilter(tgt *proc.Target, g *proc.G, filter *api.ListGoroutinesFilter) bool {
  1666  	var val bool
  1667  	switch filter.Kind {
  1668  	default:
  1669  		fallthrough
  1670  	case api.GoroutineFieldNone:
  1671  		val = true
  1672  	case api.GoroutineCurrentLoc:
  1673  		val = matchGoroutineLocFilter(g.CurrentLoc, filter.Arg)
  1674  	case api.GoroutineUserLoc:
  1675  		val = matchGoroutineLocFilter(g.UserCurrent(), filter.Arg)
  1676  	case api.GoroutineGoLoc:
  1677  		val = matchGoroutineLocFilter(g.Go(), filter.Arg)
  1678  	case api.GoroutineStartLoc:
  1679  		val = matchGoroutineLocFilter(g.StartLoc(tgt), filter.Arg)
  1680  	case api.GoroutineLabel:
  1681  		idx := strings.Index(filter.Arg, "=")
  1682  		if idx >= 0 {
  1683  			val = g.Labels()[filter.Arg[:idx]] == filter.Arg[idx+1:]
  1684  		} else {
  1685  			_, val = g.Labels()[filter.Arg]
  1686  		}
  1687  	case api.GoroutineRunning:
  1688  		val = g.Thread != nil
  1689  	case api.GoroutineUser:
  1690  		val = !g.System(tgt)
  1691  	case api.GoroutineWaitingOnChannel:
  1692  		val = true // handled elsewhere
  1693  	}
  1694  	if filter.Negated {
  1695  		val = !val
  1696  	}
  1697  	return val
  1698  }
  1699  
  1700  func matchGoroutineLocFilter(loc proc.Location, arg string) bool {
  1701  	return strings.Contains(formatLoc(loc), arg)
  1702  }
  1703  
  1704  func formatLoc(loc proc.Location) string {
  1705  	fnname := "?"
  1706  	if loc.Fn != nil {
  1707  		fnname = loc.Fn.Name
  1708  	}
  1709  	return fmt.Sprintf("%s:%d in %s", loc.File, loc.Line, fnname)
  1710  }
  1711  
  1712  // GroupGoroutines divides goroutines in gs into groups as specified by
  1713  // group.{GroupBy,GroupByKey}. A maximum of group.MaxGroupMembers are saved in
  1714  // each group, but the total number of goroutines in each group is recorded. If
  1715  // group.MaxGroups is set, then at most that many groups are returned. If some
  1716  // groups end up being dropped because of this limit, the tooManyGroups return
  1717  // value is set.
  1718  //
  1719  // The first return value represents the goroutines that have been included in
  1720  // one of the returned groups (subject to the MaxGroupMembers and MaxGroups
  1721  // limits). The second return value represents the groups.
  1722  func (d *Debugger) GroupGoroutines(gs []*proc.G, group *api.GoroutineGroupingOptions) ([]*proc.G, []api.GoroutineGroup, bool) {
  1723  	if group.GroupBy == api.GoroutineFieldNone {
  1724  		return gs, nil, false
  1725  	}
  1726  	d.targetMutex.Lock()
  1727  	defer d.targetMutex.Unlock()
  1728  
  1729  	groupMembers := map[string][]*proc.G{}
  1730  	totals := map[string]int{}
  1731  
  1732  	for _, g := range gs {
  1733  		var key string
  1734  		switch group.GroupBy {
  1735  		case api.GoroutineCurrentLoc:
  1736  			key = formatLoc(g.CurrentLoc)
  1737  		case api.GoroutineUserLoc:
  1738  			key = formatLoc(g.UserCurrent())
  1739  		case api.GoroutineGoLoc:
  1740  			key = formatLoc(g.Go())
  1741  		case api.GoroutineStartLoc:
  1742  			key = formatLoc(g.StartLoc(d.target.Selected))
  1743  		case api.GoroutineLabel:
  1744  			key = fmt.Sprintf("%s=%s", group.GroupByKey, g.Labels()[group.GroupByKey])
  1745  		case api.GoroutineRunning:
  1746  			key = fmt.Sprintf("running=%v", g.Thread != nil)
  1747  		case api.GoroutineUser:
  1748  			key = fmt.Sprintf("user=%v", !g.System(d.target.Selected))
  1749  		}
  1750  		if len(groupMembers[key]) < group.MaxGroupMembers {
  1751  			groupMembers[key] = append(groupMembers[key], g)
  1752  		}
  1753  		totals[key]++
  1754  	}
  1755  
  1756  	keys := make([]string, 0, len(groupMembers))
  1757  	for key := range groupMembers {
  1758  		keys = append(keys, key)
  1759  	}
  1760  	sort.Strings(keys)
  1761  
  1762  	tooManyGroups := false
  1763  	gsout := []*proc.G{}
  1764  	groups := []api.GoroutineGroup{}
  1765  	for _, key := range keys {
  1766  		if group.MaxGroups > 0 && len(groups) >= group.MaxGroups {
  1767  			tooManyGroups = true
  1768  			break
  1769  		}
  1770  		groups = append(groups, api.GoroutineGroup{Name: key, Offset: len(gsout), Count: len(groupMembers[key]), Total: totals[key]})
  1771  		gsout = append(gsout, groupMembers[key]...)
  1772  	}
  1773  	return gsout, groups, tooManyGroups
  1774  }
  1775  
  1776  // Stacktrace returns a list of Stackframes for the given goroutine. The
  1777  // length of the returned list will be min(stack_len, depth).
  1778  // If 'full' is true, then local vars, function args, etc will be returned as well.
  1779  func (d *Debugger) Stacktrace(goroutineID int64, depth int, opts api.StacktraceOptions) ([]proc.Stackframe, error) {
  1780  	d.targetMutex.Lock()
  1781  	defer d.targetMutex.Unlock()
  1782  
  1783  	if _, err := d.target.Valid(); err != nil {
  1784  		return nil, err
  1785  	}
  1786  
  1787  	g, err := proc.FindGoroutine(d.target.Selected, goroutineID)
  1788  	if err != nil {
  1789  		return nil, err
  1790  	}
  1791  
  1792  	if g == nil {
  1793  		return proc.ThreadStacktrace(d.target.Selected, d.target.Selected.CurrentThread(), depth)
  1794  	} else {
  1795  		return proc.GoroutineStacktrace(d.target.Selected, g, depth, proc.StacktraceOptions(opts))
  1796  	}
  1797  }
  1798  
  1799  // Ancestors returns the stacktraces for the ancestors of a goroutine.
  1800  func (d *Debugger) Ancestors(goroutineID int64, numAncestors, depth int) ([]api.Ancestor, error) {
  1801  	d.targetMutex.Lock()
  1802  	defer d.targetMutex.Unlock()
  1803  
  1804  	if _, err := d.target.Valid(); err != nil {
  1805  		return nil, err
  1806  	}
  1807  
  1808  	g, err := proc.FindGoroutine(d.target.Selected, goroutineID)
  1809  	if err != nil {
  1810  		return nil, err
  1811  	}
  1812  	if g == nil {
  1813  		return nil, errors.New("no selected goroutine")
  1814  	}
  1815  
  1816  	ancestors, err := proc.Ancestors(d.target.Selected, g, numAncestors)
  1817  	if err != nil {
  1818  		return nil, err
  1819  	}
  1820  
  1821  	r := make([]api.Ancestor, len(ancestors))
  1822  	for i := range ancestors {
  1823  		r[i].ID = ancestors[i].ID
  1824  		if ancestors[i].Unreadable != nil {
  1825  			r[i].Unreadable = ancestors[i].Unreadable.Error()
  1826  			continue
  1827  		}
  1828  		frames, err := ancestors[i].Stack(depth)
  1829  		if err != nil {
  1830  			r[i].Unreadable = fmt.Sprintf("could not read ancestor stacktrace: %v", err)
  1831  			continue
  1832  		}
  1833  		r[i].Stack, err = d.convertStacktrace(frames, nil)
  1834  		if err != nil {
  1835  			r[i].Unreadable = fmt.Sprintf("could not read ancestor stacktrace: %v", err)
  1836  		}
  1837  	}
  1838  	return r, nil
  1839  }
  1840  
  1841  // ConvertStacktrace converts a slice of proc.Stackframe into a slice of
  1842  // api.Stackframe, loading local variables and arguments of each frame if
  1843  // cfg is not nil.
  1844  func (d *Debugger) ConvertStacktrace(rawlocs []proc.Stackframe, cfg *proc.LoadConfig) ([]api.Stackframe, error) {
  1845  	d.targetMutex.Lock()
  1846  	defer d.targetMutex.Unlock()
  1847  	return d.convertStacktrace(rawlocs, cfg)
  1848  }
  1849  
  1850  func (d *Debugger) convertStacktrace(rawlocs []proc.Stackframe, cfg *proc.LoadConfig) ([]api.Stackframe, error) {
  1851  	locations := make([]api.Stackframe, 0, len(rawlocs))
  1852  	for i := range rawlocs {
  1853  		frame := api.Stackframe{
  1854  			Location: api.ConvertLocation(rawlocs[i].Call),
  1855  
  1856  			FrameOffset:        rawlocs[i].FrameOffset(),
  1857  			FramePointerOffset: rawlocs[i].FramePointerOffset(),
  1858  
  1859  			Defers: d.convertDefers(rawlocs[i].Defers),
  1860  
  1861  			Bottom: rawlocs[i].Bottom,
  1862  		}
  1863  		if rawlocs[i].Err != nil {
  1864  			frame.Err = rawlocs[i].Err.Error()
  1865  		}
  1866  		if cfg != nil && rawlocs[i].Current.Fn != nil {
  1867  			var err error
  1868  			scope := proc.FrameToScope(d.target.Selected, d.target.Selected.Memory(), nil, 0, rawlocs[i:]...)
  1869  			locals, err := scope.LocalVariables(*cfg)
  1870  			if err != nil {
  1871  				return nil, err
  1872  			}
  1873  			arguments, err := scope.FunctionArguments(*cfg)
  1874  			if err != nil {
  1875  				return nil, err
  1876  			}
  1877  
  1878  			frame.Locals = api.ConvertVars(locals)
  1879  			frame.Arguments = api.ConvertVars(arguments)
  1880  		}
  1881  		locations = append(locations, frame)
  1882  	}
  1883  
  1884  	return locations, nil
  1885  }
  1886  
  1887  func (d *Debugger) convertDefers(defers []*proc.Defer) []api.Defer {
  1888  	r := make([]api.Defer, len(defers))
  1889  	for i := range defers {
  1890  		ddf, ddl, ddfn := defers[i].DeferredFunc(d.target.Selected)
  1891  		drf, drl, drfn := d.target.Selected.BinInfo().PCToLine(defers[i].DeferPC)
  1892  
  1893  		if defers[i].Unreadable != nil {
  1894  			r[i].Unreadable = defers[i].Unreadable.Error()
  1895  		} else {
  1896  			var entry uint64 = defers[i].DeferPC
  1897  			if ddfn != nil {
  1898  				entry = ddfn.Entry
  1899  			}
  1900  			r[i] = api.Defer{
  1901  				DeferredLoc: api.ConvertLocation(proc.Location{
  1902  					PC:   entry,
  1903  					File: ddf,
  1904  					Line: ddl,
  1905  					Fn:   ddfn,
  1906  				}),
  1907  				DeferLoc: api.ConvertLocation(proc.Location{
  1908  					PC:   defers[i].DeferPC,
  1909  					File: drf,
  1910  					Line: drl,
  1911  					Fn:   drfn,
  1912  				}),
  1913  				SP: defers[i].SP,
  1914  			}
  1915  		}
  1916  
  1917  	}
  1918  
  1919  	return r
  1920  }
  1921  
  1922  // CurrentPackage returns the fully qualified name of the
  1923  // package corresponding to the function location of the
  1924  // current thread.
  1925  func (d *Debugger) CurrentPackage() (string, error) {
  1926  	d.targetMutex.Lock()
  1927  	defer d.targetMutex.Unlock()
  1928  
  1929  	if _, err := d.target.Valid(); err != nil {
  1930  		return "", err
  1931  	}
  1932  	loc, err := d.target.Selected.CurrentThread().Location()
  1933  	if err != nil {
  1934  		return "", err
  1935  	}
  1936  	if loc.Fn == nil {
  1937  		return "", fmt.Errorf("unable to determine current package due to unspecified function location")
  1938  	}
  1939  	return loc.Fn.PackageName(), nil
  1940  }
  1941  
  1942  // FindLocation will find the location specified by 'locStr'.
  1943  func (d *Debugger) FindLocation(goid int64, frame, deferredCall int, locStr string, includeNonExecutableLines bool, substitutePathRules [][2]string) ([]api.Location, string, error) {
  1944  	d.targetMutex.Lock()
  1945  	defer d.targetMutex.Unlock()
  1946  
  1947  	if _, err := d.target.Valid(); err != nil {
  1948  		return nil, "", err
  1949  	}
  1950  
  1951  	loc, err := locspec.Parse(locStr)
  1952  	if err != nil {
  1953  		return nil, "", err
  1954  	}
  1955  
  1956  	return d.findLocation(goid, frame, deferredCall, locStr, loc, includeNonExecutableLines, substitutePathRules)
  1957  }
  1958  
  1959  // FindLocationSpec will find the location specified by 'locStr' and 'locSpec'.
  1960  // 'locSpec' should be the result of calling 'locspec.Parse(locStr)'. 'locStr'
  1961  // is also passed, because it made be used to broaden the search criteria, if
  1962  // the parsed result did not find anything.
  1963  func (d *Debugger) FindLocationSpec(goid int64, frame, deferredCall int, locStr string, locSpec locspec.LocationSpec, includeNonExecutableLines bool, substitutePathRules [][2]string) ([]api.Location, error) {
  1964  	d.targetMutex.Lock()
  1965  	defer d.targetMutex.Unlock()
  1966  
  1967  	if _, err := d.target.Valid(); err != nil {
  1968  		return nil, err
  1969  	}
  1970  
  1971  	locs, _, err := d.findLocation(goid, frame, deferredCall, locStr, locSpec, includeNonExecutableLines, substitutePathRules)
  1972  	return locs, err
  1973  }
  1974  
  1975  func (d *Debugger) findLocation(goid int64, frame, deferredCall int, locStr string, locSpec locspec.LocationSpec, includeNonExecutableLines bool, substitutePathRules [][2]string) ([]api.Location, string, error) {
  1976  	locations := []api.Location{}
  1977  	t := proc.ValidTargets{Group: d.target}
  1978  	subst := ""
  1979  	for t.Next() {
  1980  		pid := t.Pid()
  1981  		s, _ := proc.ConvertEvalScope(t.Target, goid, frame, deferredCall)
  1982  		locs, s1, err := locSpec.Find(t.Target, d.processArgs, s, locStr, includeNonExecutableLines, substitutePathRules)
  1983  		if s1 != "" {
  1984  			subst = s1
  1985  		}
  1986  		if err != nil {
  1987  			return nil, "", err
  1988  		}
  1989  		for i := range locs {
  1990  			if locs[i].PC == 0 {
  1991  				continue
  1992  			}
  1993  			file, line, fn := t.BinInfo().PCToLine(locs[i].PC)
  1994  			locs[i].File = file
  1995  			locs[i].Line = line
  1996  			locs[i].Function = api.ConvertFunction(fn)
  1997  			locs[i].PCPids = make([]int, len(locs[i].PCs))
  1998  			for j := range locs[i].PCs {
  1999  				locs[i].PCPids[j] = pid
  2000  			}
  2001  		}
  2002  		locations = append(locations, locs...)
  2003  	}
  2004  	return locations, subst, nil
  2005  }
  2006  
  2007  // Disassemble code between startPC and endPC.
  2008  // if endPC == 0 it will find the function containing startPC and disassemble the whole function.
  2009  func (d *Debugger) Disassemble(goroutineID int64, addr1, addr2 uint64) ([]proc.AsmInstruction, error) {
  2010  	d.targetMutex.Lock()
  2011  	defer d.targetMutex.Unlock()
  2012  
  2013  	if _, err := d.target.Valid(); err != nil {
  2014  		return nil, err
  2015  	}
  2016  
  2017  	if addr2 == 0 {
  2018  		fn := d.target.Selected.BinInfo().PCToFunc(addr1)
  2019  		if fn == nil {
  2020  			return nil, fmt.Errorf("address %#x does not belong to any function", addr1)
  2021  		}
  2022  		addr1 = fn.Entry
  2023  		addr2 = fn.End
  2024  	}
  2025  
  2026  	g, err := proc.FindGoroutine(d.target.Selected, goroutineID)
  2027  	if err != nil {
  2028  		return nil, err
  2029  	}
  2030  
  2031  	curthread := d.target.Selected.CurrentThread()
  2032  	if g != nil && g.Thread != nil {
  2033  		curthread = g.Thread
  2034  	}
  2035  	regs, _ := curthread.Registers()
  2036  
  2037  	return proc.Disassemble(d.target.Selected.Memory(), regs, d.target.Selected.Breakpoints(), d.target.Selected.BinInfo(), addr1, addr2)
  2038  }
  2039  
  2040  func (d *Debugger) AsmInstructionText(inst *proc.AsmInstruction, flavour proc.AssemblyFlavour) string {
  2041  	d.targetMutex.Lock()
  2042  	defer d.targetMutex.Unlock()
  2043  	return inst.Text(flavour, d.target.Selected.BinInfo())
  2044  }
  2045  
  2046  // Recorded returns true if the target is a recording.
  2047  func (d *Debugger) Recorded() (recorded bool, tracedir string) {
  2048  	d.targetMutex.Lock()
  2049  	defer d.targetMutex.Unlock()
  2050  	return d.target.Recorded()
  2051  }
  2052  
  2053  // FindThreadReturnValues returns the return values of the function that
  2054  // the thread of the given 'id' just stepped out of.
  2055  func (d *Debugger) FindThreadReturnValues(id int, cfg proc.LoadConfig) ([]*proc.Variable, error) {
  2056  	d.targetMutex.Lock()
  2057  	defer d.targetMutex.Unlock()
  2058  
  2059  	if _, err := d.target.Valid(); err != nil {
  2060  		return nil, err
  2061  	}
  2062  
  2063  	thread, found := d.target.Selected.FindThread(id)
  2064  	if !found {
  2065  		return nil, fmt.Errorf("could not find thread %d", id)
  2066  	}
  2067  
  2068  	return thread.Common().ReturnValues(cfg), nil
  2069  }
  2070  
  2071  // Checkpoint will set a checkpoint specified by the locspec.
  2072  func (d *Debugger) Checkpoint(where string) (int, error) {
  2073  	d.targetMutex.Lock()
  2074  	defer d.targetMutex.Unlock()
  2075  	return d.target.Checkpoint(where)
  2076  }
  2077  
  2078  // Checkpoints will return a list of checkpoints.
  2079  func (d *Debugger) Checkpoints() ([]proc.Checkpoint, error) {
  2080  	d.targetMutex.Lock()
  2081  	defer d.targetMutex.Unlock()
  2082  	return d.target.Checkpoints()
  2083  }
  2084  
  2085  // ClearCheckpoint will clear the checkpoint of the given ID.
  2086  func (d *Debugger) ClearCheckpoint(id int) error {
  2087  	d.targetMutex.Lock()
  2088  	defer d.targetMutex.Unlock()
  2089  	return d.target.ClearCheckpoint(id)
  2090  }
  2091  
  2092  // ListDynamicLibraries returns a list of loaded dynamic libraries.
  2093  func (d *Debugger) ListDynamicLibraries() []*proc.Image {
  2094  	d.targetMutex.Lock()
  2095  	defer d.targetMutex.Unlock()
  2096  	return d.target.Selected.BinInfo().Images[1:] // skips the first image because it's the executable file
  2097  
  2098  }
  2099  
  2100  // ExamineMemory returns the raw memory stored at the given address.
  2101  // The amount of data to be read is specified by length.
  2102  // This function will return an error if it reads less than `length` bytes.
  2103  func (d *Debugger) ExamineMemory(address uint64, length int) ([]byte, error) {
  2104  	d.targetMutex.Lock()
  2105  	defer d.targetMutex.Unlock()
  2106  
  2107  	mem := d.target.Selected.Memory()
  2108  	data := make([]byte, length)
  2109  	n, err := mem.ReadMemory(data, address)
  2110  	if err != nil {
  2111  		return nil, err
  2112  	}
  2113  	if length != n {
  2114  		return nil, errors.New("the specific range has exceeded readable area")
  2115  	}
  2116  	return data, nil
  2117  }
  2118  
  2119  func (d *Debugger) GetVersion(out *api.GetVersionOut) error {
  2120  	if d.config.CoreFile != "" {
  2121  		if d.config.Backend == "rr" {
  2122  			out.Backend = "rr"
  2123  		} else {
  2124  			out.Backend = "core"
  2125  		}
  2126  	} else {
  2127  		if d.config.Backend == "default" {
  2128  			if runtime.GOOS == "darwin" {
  2129  				out.Backend = "lldb"
  2130  			} else {
  2131  				out.Backend = "native"
  2132  			}
  2133  		} else {
  2134  			out.Backend = d.config.Backend
  2135  		}
  2136  	}
  2137  
  2138  	if !d.isRecording() && !d.IsRunning() {
  2139  		out.TargetGoVersion = d.target.Selected.BinInfo().Producer()
  2140  	}
  2141  
  2142  	out.MinSupportedVersionOfGo = fmt.Sprintf("%d.%d.0", goversion.MinSupportedVersionOfGoMajor, goversion.MinSupportedVersionOfGoMinor)
  2143  	out.MaxSupportedVersionOfGo = fmt.Sprintf("%d.%d.0", goversion.MaxSupportedVersionOfGoMajor, goversion.MaxSupportedVersionOfGoMinor)
  2144  
  2145  	return nil
  2146  }
  2147  
  2148  // ListPackagesBuildInfo returns the list of packages used by the program along with
  2149  // the directory where each package was compiled and optionally the list of
  2150  // files constituting the package.
  2151  func (d *Debugger) ListPackagesBuildInfo(includeFiles bool) []*proc.PackageBuildInfo {
  2152  	d.targetMutex.Lock()
  2153  	defer d.targetMutex.Unlock()
  2154  	return d.target.Selected.BinInfo().ListPackagesBuildInfo(includeFiles)
  2155  }
  2156  
  2157  // StopRecording stops a recording (if one is in progress)
  2158  func (d *Debugger) StopRecording() error {
  2159  	d.recordMutex.Lock()
  2160  	defer d.recordMutex.Unlock()
  2161  	if d.stopRecording == nil {
  2162  		return ErrNotRecording
  2163  	}
  2164  	return d.stopRecording()
  2165  }
  2166  
  2167  // StopReason returns the reason the reason why the target process is stopped.
  2168  // A process could be stopped for multiple simultaneous reasons, in which
  2169  // case only one will be reported.
  2170  func (d *Debugger) StopReason() proc.StopReason {
  2171  	d.targetMutex.Lock()
  2172  	defer d.targetMutex.Unlock()
  2173  	return d.target.Selected.StopReason
  2174  }
  2175  
  2176  // LockTarget acquires the target mutex.
  2177  func (d *Debugger) LockTarget() {
  2178  	d.targetMutex.Lock()
  2179  }
  2180  
  2181  // UnlockTarget releases the target mutex.
  2182  func (d *Debugger) UnlockTarget() {
  2183  	d.targetMutex.Unlock()
  2184  }
  2185  
  2186  // DumpStart starts a core dump to dest.
  2187  func (d *Debugger) DumpStart(dest string) error {
  2188  	d.targetMutex.Lock()
  2189  	// targetMutex will only be unlocked when the dump is done
  2190  
  2191  	//TODO(aarzilli): what do we do if the user switches to a different target after starting a dump but before it's finished?
  2192  
  2193  	if !d.target.CanDump {
  2194  		d.targetMutex.Unlock()
  2195  		return ErrCoreDumpNotSupported
  2196  	}
  2197  
  2198  	d.dumpState.Mutex.Lock()
  2199  	defer d.dumpState.Mutex.Unlock()
  2200  
  2201  	if d.dumpState.Dumping {
  2202  		d.targetMutex.Unlock()
  2203  		return ErrCoreDumpInProgress
  2204  	}
  2205  
  2206  	fh, err := os.Create(dest)
  2207  	if err != nil {
  2208  		d.targetMutex.Unlock()
  2209  		return err
  2210  	}
  2211  
  2212  	d.dumpState.Dumping = true
  2213  	d.dumpState.AllDone = false
  2214  	d.dumpState.Canceled = false
  2215  	d.dumpState.DoneChan = make(chan struct{})
  2216  	d.dumpState.ThreadsDone = 0
  2217  	d.dumpState.ThreadsTotal = 0
  2218  	d.dumpState.MemDone = 0
  2219  	d.dumpState.MemTotal = 0
  2220  	d.dumpState.Err = nil
  2221  	go func() {
  2222  		defer d.targetMutex.Unlock()
  2223  		d.target.Selected.Dump(fh, 0, &d.dumpState)
  2224  	}()
  2225  
  2226  	return nil
  2227  }
  2228  
  2229  // DumpWait waits for the dump to finish, or for the duration of wait.
  2230  // Returns the state of the dump.
  2231  // If wait == 0 returns immediately.
  2232  func (d *Debugger) DumpWait(wait time.Duration) *proc.DumpState {
  2233  	d.dumpState.Mutex.Lock()
  2234  	if !d.dumpState.Dumping {
  2235  		d.dumpState.Mutex.Unlock()
  2236  		return &d.dumpState
  2237  	}
  2238  	d.dumpState.Mutex.Unlock()
  2239  
  2240  	if wait > 0 {
  2241  		alarm := time.After(wait)
  2242  		select {
  2243  		case <-alarm:
  2244  		case <-d.dumpState.DoneChan:
  2245  		}
  2246  	}
  2247  
  2248  	return &d.dumpState
  2249  }
  2250  
  2251  // DumpCancel cancels a dump in progress
  2252  func (d *Debugger) DumpCancel() error {
  2253  	d.dumpState.Mutex.Lock()
  2254  	d.dumpState.Canceled = true
  2255  	d.dumpState.Mutex.Unlock()
  2256  	return nil
  2257  }
  2258  
  2259  func (d *Debugger) Target() *proc.Target {
  2260  	return d.target.Selected
  2261  }
  2262  
  2263  func (d *Debugger) TargetGroup() *proc.TargetGroup {
  2264  	return d.target
  2265  }
  2266  
  2267  func (d *Debugger) BuildID() string {
  2268  	return d.target.Selected.BinInfo().BuildID
  2269  }
  2270  
  2271  func (d *Debugger) AttachPid() int {
  2272  	return d.config.AttachPid
  2273  }
  2274  
  2275  func (d *Debugger) GetBufferedTracepoints() []api.TracepointResult {
  2276  	traces := d.target.Selected.GetBufferedTracepoints()
  2277  	if traces == nil {
  2278  		return nil
  2279  	}
  2280  	results := make([]api.TracepointResult, len(traces))
  2281  	for i, trace := range traces {
  2282  		results[i].IsRet = trace.IsRet
  2283  
  2284  		f, l, fn := d.target.Selected.BinInfo().PCToLine(uint64(trace.FnAddr))
  2285  
  2286  		results[i].FunctionName = fn.Name
  2287  		results[i].Line = l
  2288  		results[i].File = f
  2289  		results[i].GoroutineID = trace.GoroutineID
  2290  
  2291  		for _, p := range trace.InputParams {
  2292  			results[i].InputParams = append(results[i].InputParams, *api.ConvertVar(p))
  2293  		}
  2294  		for _, p := range trace.ReturnParams {
  2295  			results[i].ReturnParams = append(results[i].ReturnParams, *api.ConvertVar(p))
  2296  		}
  2297  	}
  2298  	return results
  2299  }
  2300  
  2301  // FollowExec enabled or disables follow exec mode.
  2302  func (d *Debugger) FollowExec(enabled bool, regex string) error {
  2303  	d.targetMutex.Lock()
  2304  	defer d.targetMutex.Unlock()
  2305  	return d.target.FollowExec(enabled, regex)
  2306  }
  2307  
  2308  // FollowExecEnabled returns true if follow exec mode is enabled.
  2309  func (d *Debugger) FollowExecEnabled() bool {
  2310  	d.targetMutex.Lock()
  2311  	defer d.targetMutex.Unlock()
  2312  	return d.target.FollowExecEnabled()
  2313  }
  2314  
  2315  func (d *Debugger) SetDebugInfoDirectories(v []string) {
  2316  	d.recordMutex.Lock()
  2317  	defer d.recordMutex.Unlock()
  2318  	it := proc.ValidTargets{Group: d.target}
  2319  	for it.Next() {
  2320  		it.BinInfo().DebugInfoDirectories = v
  2321  	}
  2322  }
  2323  
  2324  func (d *Debugger) DebugInfoDirectories() []string {
  2325  	d.recordMutex.Lock()
  2326  	defer d.recordMutex.Unlock()
  2327  	return d.target.Selected.BinInfo().DebugInfoDirectories
  2328  }
  2329  
  2330  // ChanGoroutines returns the list of goroutines waiting on the channel specified by expr.
  2331  func (d *Debugger) ChanGoroutines(goid int64, frame, deferredCall int, expr string, start, count int) ([]*proc.G, error) {
  2332  	d.targetMutex.Lock()
  2333  	defer d.targetMutex.Unlock()
  2334  	s, err := proc.ConvertEvalScope(d.target.Selected, goid, frame, deferredCall)
  2335  	if err != nil {
  2336  		return nil, err
  2337  	}
  2338  
  2339  	goids, err := s.ChanGoroutines(expr, start, count)
  2340  	if err != nil {
  2341  		return nil, err
  2342  	}
  2343  
  2344  	gs := make([]*proc.G, len(goids))
  2345  	for i := range goids {
  2346  		g, err := proc.FindGoroutine(d.target.Selected, goids[i])
  2347  		if g == nil {
  2348  			g = &proc.G{Unreadable: err}
  2349  		}
  2350  		gs[i] = g
  2351  	}
  2352  	return gs, nil
  2353  }
  2354  
  2355  func go11DecodeErrorCheck(err error) error {
  2356  	if _, isdecodeerr := err.(dwarf.DecodeError); !isdecodeerr {
  2357  		return err
  2358  	}
  2359  
  2360  	gover, ok := goversion.Installed()
  2361  	if !ok || !gover.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 11, Rev: -1}) || goversion.VersionAfterOrEqual(runtime.Version(), 1, 11) {
  2362  		return err
  2363  	}
  2364  
  2365  	return fmt.Errorf("executables built by Go 1.11 or later need Delve built by Go 1.11 or later")
  2366  }
  2367  
  2368  const NoDebugWarning string = "debuggee must not be built with 'go run' or -ldflags='-s -w', which strip debug info"
  2369  
  2370  func noDebugErrorWarning(err error) error {
  2371  	if _, isdecodeerr := err.(dwarf.DecodeError); isdecodeerr || strings.Contains(err.Error(), "could not open debug info") {
  2372  		return fmt.Errorf("%s - %s", err.Error(), NoDebugWarning)
  2373  	}
  2374  	return err
  2375  }
  2376  
  2377  func verifyBinaryFormat(exePath string) (string, error) {
  2378  	fullpath, err := filepath.Abs(exePath)
  2379  	if err != nil {
  2380  		return "", err
  2381  	}
  2382  
  2383  	f, err := os.Open(fullpath)
  2384  	if err != nil {
  2385  		return "", err
  2386  	}
  2387  	defer f.Close()
  2388  
  2389  	// Skip this check on Windows.
  2390  	// TODO(derekparker) exec.LookPath looks for valid Windows extensions.
  2391  	// We don't create our binaries with valid extensions, even though we should.
  2392  	// Skip this check for now.
  2393  	if runtime.GOOS != "windows" {
  2394  		_, err = exec.LookPath(fullpath)
  2395  		if err != nil {
  2396  			return "", api.ErrNotExecutable
  2397  		}
  2398  	}
  2399  
  2400  	// check that the binary format is what we expect for the host system
  2401  	var exe io.Closer
  2402  	switch runtime.GOOS {
  2403  	case "darwin":
  2404  		exe, err = macho.NewFile(f)
  2405  	case "linux", "freebsd":
  2406  		exe, err = elf.NewFile(f)
  2407  	case "windows":
  2408  		exe, err = pe.NewFile(f)
  2409  	default:
  2410  		panic("attempting to open file Delve cannot parse")
  2411  	}
  2412  
  2413  	if err != nil {
  2414  		return "", api.ErrNotExecutable
  2415  	}
  2416  	exe.Close()
  2417  	return fullpath, nil
  2418  }
  2419  
  2420  var attachErrorMessage = attachErrorMessageDefault
  2421  
  2422  func attachErrorMessageDefault(pid int, err error) error {
  2423  	return fmt.Errorf("could not attach to pid %d: %s", pid, err)
  2424  }