github.com/neilgarb/delve@v1.9.2-nobreaks/pkg/proc/proc_test.go (about)

     1  package proc_test
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"flag"
     7  	"fmt"
     8  	"go/ast"
     9  	"go/constant"
    10  	"go/token"
    11  	"io/ioutil"
    12  	"math/rand"
    13  	"net"
    14  	"net/http"
    15  	"os"
    16  	"os/exec"
    17  	"path/filepath"
    18  	"reflect"
    19  	"runtime"
    20  	"sort"
    21  	"strconv"
    22  	"strings"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/go-delve/delve/pkg/dwarf/frame"
    27  	"github.com/go-delve/delve/pkg/dwarf/op"
    28  	"github.com/go-delve/delve/pkg/dwarf/regnum"
    29  	"github.com/go-delve/delve/pkg/goversion"
    30  	"github.com/go-delve/delve/pkg/logflags"
    31  	"github.com/go-delve/delve/pkg/proc"
    32  	"github.com/go-delve/delve/pkg/proc/core"
    33  	"github.com/go-delve/delve/pkg/proc/gdbserial"
    34  	"github.com/go-delve/delve/pkg/proc/native"
    35  	protest "github.com/go-delve/delve/pkg/proc/test"
    36  	"github.com/go-delve/delve/service/api"
    37  )
    38  
    39  var normalLoadConfig = proc.LoadConfig{true, 1, 64, 64, -1, 0}
    40  var testBackend, buildMode string
    41  
    42  func init() {
    43  	runtime.GOMAXPROCS(4)
    44  	os.Setenv("GOMAXPROCS", "4")
    45  }
    46  
    47  func TestMain(m *testing.M) {
    48  	flag.StringVar(&testBackend, "backend", "", "selects backend")
    49  	flag.StringVar(&buildMode, "test-buildmode", "", "selects build mode")
    50  	var logConf string
    51  	flag.StringVar(&logConf, "log", "", "configures logging")
    52  	flag.Parse()
    53  	protest.DefaultTestBackend(&testBackend)
    54  	if buildMode != "" && buildMode != "pie" {
    55  		fmt.Fprintf(os.Stderr, "unknown build mode %q", buildMode)
    56  		os.Exit(1)
    57  	}
    58  	logflags.Setup(logConf != "", logConf, "")
    59  	os.Exit(protest.RunTestsWithFixtures(m))
    60  }
    61  
    62  func matchSkipConditions(conditions ...string) bool {
    63  	for _, cond := range conditions {
    64  		condfound := false
    65  		for _, s := range []string{runtime.GOOS, runtime.GOARCH, testBackend, buildMode} {
    66  			if s == cond {
    67  				condfound = true
    68  				break
    69  			}
    70  		}
    71  		if !condfound {
    72  			return false
    73  		}
    74  	}
    75  	return true
    76  }
    77  
    78  func skipOn(t testing.TB, reason string, conditions ...string) {
    79  	if matchSkipConditions(conditions...) {
    80  		t.Skipf("skipped on %s: %s", strings.Join(conditions, "/"), reason)
    81  	}
    82  }
    83  
    84  func skipUnlessOn(t testing.TB, reason string, conditions ...string) {
    85  	if !matchSkipConditions(conditions...) {
    86  		t.Skipf("skipped on %s: %s", strings.Join(conditions, "/"), reason)
    87  	}
    88  }
    89  
    90  func withTestProcess(name string, t testing.TB, fn func(p *proc.Target, fixture protest.Fixture)) {
    91  	withTestProcessArgs(name, t, ".", []string{}, 0, fn)
    92  }
    93  
    94  func withTestProcessArgs(name string, t testing.TB, wd string, args []string, buildFlags protest.BuildFlags, fn func(p *proc.Target, fixture protest.Fixture)) {
    95  	if buildMode == "pie" {
    96  		buildFlags |= protest.BuildModePIE
    97  	}
    98  	fixture := protest.BuildFixture(name, buildFlags)
    99  	var p *proc.Target
   100  	var err error
   101  	var tracedir string
   102  
   103  	switch testBackend {
   104  	case "native":
   105  		p, err = native.Launch(append([]string{fixture.Path}, args...), wd, 0, []string{}, "", [3]string{})
   106  	case "lldb":
   107  		p, err = gdbserial.LLDBLaunch(append([]string{fixture.Path}, args...), wd, 0, []string{}, "", [3]string{})
   108  	case "rr":
   109  		protest.MustHaveRecordingAllowed(t)
   110  		t.Log("recording")
   111  		p, tracedir, err = gdbserial.RecordAndReplay(append([]string{fixture.Path}, args...), wd, true, []string{}, [3]string{})
   112  		t.Logf("replaying %q", tracedir)
   113  	default:
   114  		t.Fatal("unknown backend")
   115  	}
   116  	if err != nil {
   117  		t.Fatal("Launch():", err)
   118  	}
   119  
   120  	defer func() {
   121  		p.Detach(true)
   122  	}()
   123  
   124  	fn(p, fixture)
   125  }
   126  
   127  func getRegisters(p *proc.Target, t *testing.T) proc.Registers {
   128  	regs, err := p.CurrentThread().Registers()
   129  	if err != nil {
   130  		t.Fatal("Registers():", err)
   131  	}
   132  
   133  	return regs
   134  }
   135  
   136  func dataAtAddr(thread proc.MemoryReadWriter, addr uint64) ([]byte, error) {
   137  	data := make([]byte, 1)
   138  	_, err := thread.ReadMemory(data, addr)
   139  	return data, err
   140  }
   141  
   142  func assertNoError(err error, t testing.TB, s string) {
   143  	if err != nil {
   144  		_, file, line, _ := runtime.Caller(1)
   145  		fname := filepath.Base(file)
   146  		t.Fatalf("failed assertion at %s:%d: %s - %s\n", fname, line, s, err)
   147  	}
   148  }
   149  
   150  func currentPC(p *proc.Target, t *testing.T) uint64 {
   151  	regs, err := p.CurrentThread().Registers()
   152  	if err != nil {
   153  		t.Fatal(err)
   154  	}
   155  
   156  	return regs.PC()
   157  }
   158  
   159  func currentLineNumber(p *proc.Target, t *testing.T) (string, int) {
   160  	pc := currentPC(p, t)
   161  	f, l, _ := p.BinInfo().PCToLine(pc)
   162  	return f, l
   163  }
   164  
   165  func assertLineNumber(p *proc.Target, t *testing.T, lineno int, descr string) (string, int) {
   166  	f, l := currentLineNumber(p, t)
   167  	if l != lineno {
   168  		_, callerFile, callerLine, _ := runtime.Caller(1)
   169  		t.Fatalf("%s expected line :%d got %s:%d\n\tat %s:%d", descr, lineno, f, l, callerFile, callerLine)
   170  	}
   171  	return f, l
   172  }
   173  
   174  func TestExit(t *testing.T) {
   175  	protest.AllowRecording(t)
   176  	withTestProcess("continuetestprog", t, func(p *proc.Target, fixture protest.Fixture) {
   177  		err := p.Continue()
   178  		pe, ok := err.(proc.ErrProcessExited)
   179  		if !ok {
   180  			t.Fatalf("Continue() returned unexpected error type %s", err)
   181  		}
   182  		if pe.Status != 0 {
   183  			t.Errorf("Unexpected error status: %d", pe.Status)
   184  		}
   185  		if pe.Pid != p.Pid() {
   186  			t.Errorf("Unexpected process id: %d", pe.Pid)
   187  		}
   188  	})
   189  }
   190  
   191  func TestExitAfterContinue(t *testing.T) {
   192  	protest.AllowRecording(t)
   193  	withTestProcess("continuetestprog", t, func(p *proc.Target, fixture protest.Fixture) {
   194  		setFunctionBreakpoint(p, t, "main.sayhi")
   195  		assertNoError(p.Continue(), t, "First Continue()")
   196  		err := p.Continue()
   197  		pe, ok := err.(proc.ErrProcessExited)
   198  		if !ok {
   199  			t.Fatalf("Continue() returned unexpected error type %s", pe)
   200  		}
   201  		if pe.Status != 0 {
   202  			t.Errorf("Unexpected error status: %d", pe.Status)
   203  		}
   204  		if pe.Pid != p.Pid() {
   205  			t.Errorf("Unexpected process id: %d", pe.Pid)
   206  		}
   207  	})
   208  }
   209  
   210  func setFunctionBreakpoint(p *proc.Target, t testing.TB, fname string) *proc.Breakpoint {
   211  	_, f, l, _ := runtime.Caller(1)
   212  	f = filepath.Base(f)
   213  
   214  	addrs, err := proc.FindFunctionLocation(p, fname, 0)
   215  	if err != nil {
   216  		t.Fatalf("%s:%d: FindFunctionLocation(%s): %v", f, l, fname, err)
   217  	}
   218  	if len(addrs) != 1 {
   219  		t.Fatalf("%s:%d: setFunctionBreakpoint(%s): too many results %v", f, l, fname, addrs)
   220  	}
   221  	bp, err := p.SetBreakpoint(int(addrs[0]), addrs[0], proc.UserBreakpoint, nil)
   222  	if err != nil {
   223  		t.Fatalf("%s:%d: FindFunctionLocation(%s): %v", f, l, fname, err)
   224  	}
   225  	return bp
   226  }
   227  
   228  func setFileBreakpoint(p *proc.Target, t testing.TB, path string, lineno int) *proc.Breakpoint {
   229  	_, f, l, _ := runtime.Caller(1)
   230  	f = filepath.Base(f)
   231  
   232  	addrs, err := proc.FindFileLocation(p, path, lineno)
   233  	if err != nil {
   234  		t.Fatalf("%s:%d: FindFileLocation(%s, %d): %v", f, l, path, lineno, err)
   235  	}
   236  	if len(addrs) != 1 {
   237  		t.Fatalf("%s:%d: setFileLineBreakpoint(%s, %d): too many (or not enough) results %v", f, l, path, lineno, addrs)
   238  	}
   239  	bp, err := p.SetBreakpoint(int(addrs[0]), addrs[0], proc.UserBreakpoint, nil)
   240  	if err != nil {
   241  		t.Fatalf("%s:%d: SetBreakpoint: %v", f, l, err)
   242  	}
   243  	return bp
   244  }
   245  
   246  func findFunctionLocation(p *proc.Target, t *testing.T, fnname string) uint64 {
   247  	_, f, l, _ := runtime.Caller(1)
   248  	f = filepath.Base(f)
   249  	addrs, err := proc.FindFunctionLocation(p, fnname, 0)
   250  	if err != nil {
   251  		t.Fatalf("%s:%d: FindFunctionLocation(%s): %v", f, l, fnname, err)
   252  	}
   253  	if len(addrs) != 1 {
   254  		t.Fatalf("%s:%d: FindFunctionLocation(%s): too many results %v", f, l, fnname, addrs)
   255  	}
   256  	return addrs[0]
   257  }
   258  
   259  func findFileLocation(p *proc.Target, t *testing.T, file string, lineno int) uint64 {
   260  	_, f, l, _ := runtime.Caller(1)
   261  	f = filepath.Base(f)
   262  	addrs, err := proc.FindFileLocation(p, file, lineno)
   263  	if err != nil {
   264  		t.Fatalf("%s:%d: FindFileLocation(%s, %d): %v", f, l, file, lineno, err)
   265  	}
   266  	if len(addrs) != 1 {
   267  		t.Fatalf("%s:%d: FindFileLocation(%s, %d): too many results %v", f, l, file, lineno, addrs)
   268  	}
   269  	return addrs[0]
   270  }
   271  
   272  func TestHalt(t *testing.T) {
   273  	stopChan := make(chan interface{}, 1)
   274  	withTestProcess("loopprog", t, func(p *proc.Target, fixture protest.Fixture) {
   275  		setFunctionBreakpoint(p, t, "main.loop")
   276  		assertNoError(p.Continue(), t, "Continue")
   277  		resumeChan := make(chan struct{}, 1)
   278  		go func() {
   279  			<-resumeChan
   280  			time.Sleep(100 * time.Millisecond)
   281  			stopChan <- p.RequestManualStop()
   282  		}()
   283  		p.ResumeNotify(resumeChan)
   284  		assertNoError(p.Continue(), t, "Continue")
   285  		retVal := <-stopChan
   286  
   287  		if err, ok := retVal.(error); ok && err != nil {
   288  			t.Fatal()
   289  		}
   290  	})
   291  }
   292  
   293  func TestStep(t *testing.T) {
   294  	protest.AllowRecording(t)
   295  	withTestProcess("testprog", t, func(p *proc.Target, fixture protest.Fixture) {
   296  		setFunctionBreakpoint(p, t, "main.helloworld")
   297  		assertNoError(p.Continue(), t, "Continue()")
   298  
   299  		regs := getRegisters(p, t)
   300  		rip := regs.PC()
   301  
   302  		err := p.CurrentThread().StepInstruction()
   303  		assertNoError(err, t, "Step()")
   304  
   305  		regs = getRegisters(p, t)
   306  		if rip >= regs.PC() {
   307  			t.Errorf("Expected %#v to be greater than %#v", regs.PC(), rip)
   308  		}
   309  	})
   310  }
   311  
   312  func TestBreakpoint(t *testing.T) {
   313  	protest.AllowRecording(t)
   314  	withTestProcess("testprog", t, func(p *proc.Target, fixture protest.Fixture) {
   315  		bp := setFunctionBreakpoint(p, t, "main.helloworld")
   316  		assertNoError(p.Continue(), t, "Continue()")
   317  
   318  		regs, err := p.CurrentThread().Registers()
   319  		assertNoError(err, t, "Registers")
   320  		pc := regs.PC()
   321  
   322  		if bp.Logical.TotalHitCount != 1 {
   323  			t.Fatalf("Breakpoint should be hit once, got %d\n", bp.Logical.TotalHitCount)
   324  		}
   325  
   326  		if pc-1 != bp.Addr && pc != bp.Addr {
   327  			f, l, _ := p.BinInfo().PCToLine(pc)
   328  			t.Fatalf("Break not respected:\nPC:%#v %s:%d\nFN:%#v \n", pc, f, l, bp.Addr)
   329  		}
   330  	})
   331  }
   332  
   333  func TestBreakpointInSeparateGoRoutine(t *testing.T) {
   334  	protest.AllowRecording(t)
   335  	withTestProcess("testthreads", t, func(p *proc.Target, fixture protest.Fixture) {
   336  		setFunctionBreakpoint(p, t, "main.anotherthread")
   337  
   338  		assertNoError(p.Continue(), t, "Continue")
   339  
   340  		regs, err := p.CurrentThread().Registers()
   341  		assertNoError(err, t, "Registers")
   342  		pc := regs.PC()
   343  
   344  		f, l, _ := p.BinInfo().PCToLine(pc)
   345  		if f != "testthreads.go" && l != 8 {
   346  			t.Fatal("Program did not hit breakpoint")
   347  		}
   348  	})
   349  }
   350  
   351  func TestBreakpointWithNonExistantFunction(t *testing.T) {
   352  	withTestProcess("testprog", t, func(p *proc.Target, fixture protest.Fixture) {
   353  		_, err := p.SetBreakpoint(0, 0, proc.UserBreakpoint, nil)
   354  		if err == nil {
   355  			t.Fatal("Should not be able to break at non existent function")
   356  		}
   357  	})
   358  }
   359  
   360  func TestClearBreakpointBreakpoint(t *testing.T) {
   361  	withTestProcess("testprog", t, func(p *proc.Target, fixture protest.Fixture) {
   362  		bp := setFunctionBreakpoint(p, t, "main.sleepytime")
   363  
   364  		err := p.ClearBreakpoint(bp.Addr)
   365  		assertNoError(err, t, "ClearBreakpoint()")
   366  
   367  		data, err := dataAtAddr(p.Memory(), bp.Addr)
   368  		assertNoError(err, t, "dataAtAddr")
   369  
   370  		int3 := []byte{0xcc}
   371  		if bytes.Equal(data, int3) {
   372  			t.Fatalf("Breakpoint was not cleared data: %#v, int3: %#v", data, int3)
   373  		}
   374  
   375  		if countBreakpoints(p) != 0 {
   376  			t.Fatal("Breakpoint not removed internally")
   377  		}
   378  	})
   379  }
   380  
   381  type nextTest struct {
   382  	begin, end int
   383  }
   384  
   385  func countBreakpoints(p *proc.Target) int {
   386  	bpcount := 0
   387  	for _, bp := range p.Breakpoints().M {
   388  		if bp.LogicalID() >= 0 {
   389  			bpcount++
   390  		}
   391  	}
   392  	return bpcount
   393  }
   394  
   395  type contFunc int
   396  
   397  const (
   398  	contContinue contFunc = iota
   399  	contNext
   400  	contStep
   401  	contStepout
   402  	contReverseNext
   403  	contReverseStep
   404  	contReverseStepout
   405  	contContinueToBreakpoint
   406  )
   407  
   408  type seqTest struct {
   409  	cf  contFunc
   410  	pos interface{}
   411  }
   412  
   413  func testseq(program string, contFunc contFunc, testcases []nextTest, initialLocation string, t *testing.T) {
   414  	seqTestcases := make([]seqTest, len(testcases)+1)
   415  	seqTestcases[0] = seqTest{contContinue, testcases[0].begin}
   416  	for i := range testcases {
   417  		if i > 0 {
   418  			if testcases[i-1].end != testcases[i].begin {
   419  				panic(fmt.Errorf("begin/end mismatch at index %d", i))
   420  			}
   421  		}
   422  		seqTestcases[i+1] = seqTest{contFunc, testcases[i].end}
   423  	}
   424  	testseq2(t, program, initialLocation, seqTestcases)
   425  }
   426  
   427  const traceTestseq2 = true
   428  
   429  func testseq2(t *testing.T, program string, initialLocation string, testcases []seqTest) {
   430  	testseq2Args(".", []string{}, 0, t, program, initialLocation, testcases)
   431  }
   432  
   433  func testseq2Args(wd string, args []string, buildFlags protest.BuildFlags, t *testing.T, program string, initialLocation string, testcases []seqTest) {
   434  	protest.AllowRecording(t)
   435  	withTestProcessArgs(program, t, wd, args, buildFlags, func(p *proc.Target, fixture protest.Fixture) {
   436  		var bp *proc.Breakpoint
   437  		if initialLocation != "" {
   438  			bp = setFunctionBreakpoint(p, t, initialLocation)
   439  		} else if testcases[0].cf == contContinue {
   440  			bp = setFileBreakpoint(p, t, fixture.Source, testcases[0].pos.(int))
   441  		} else {
   442  			panic("testseq2 can not set initial breakpoint")
   443  		}
   444  		if traceTestseq2 {
   445  			t.Logf("initial breakpoint %v", bp)
   446  		}
   447  		regs, err := p.CurrentThread().Registers()
   448  		assertNoError(err, t, "Registers")
   449  
   450  		f, ln := currentLineNumber(p, t)
   451  		for i, tc := range testcases {
   452  			switch tc.cf {
   453  			case contNext:
   454  				if traceTestseq2 {
   455  					t.Log("next")
   456  				}
   457  				assertNoError(p.Next(), t, "Next() returned an error")
   458  			case contStep:
   459  				if traceTestseq2 {
   460  					t.Log("step")
   461  				}
   462  				assertNoError(p.Step(), t, "Step() returned an error")
   463  			case contStepout:
   464  				if traceTestseq2 {
   465  					t.Log("stepout")
   466  				}
   467  				assertNoError(p.StepOut(), t, "StepOut() returned an error")
   468  			case contContinue:
   469  				if traceTestseq2 {
   470  					t.Log("continue")
   471  				}
   472  				assertNoError(p.Continue(), t, "Continue() returned an error")
   473  				if i == 0 {
   474  					if traceTestseq2 {
   475  						t.Log("clearing initial breakpoint")
   476  					}
   477  					err := p.ClearBreakpoint(bp.Addr)
   478  					assertNoError(err, t, "ClearBreakpoint() returned an error")
   479  				}
   480  			case contReverseNext:
   481  				if traceTestseq2 {
   482  					t.Log("reverse-next")
   483  				}
   484  				assertNoError(p.ChangeDirection(proc.Backward), t, "direction switch")
   485  				assertNoError(p.Next(), t, "reverse Next() returned an error")
   486  				assertNoError(p.ChangeDirection(proc.Forward), t, "direction switch")
   487  			case contReverseStep:
   488  				if traceTestseq2 {
   489  					t.Log("reverse-step")
   490  				}
   491  				assertNoError(p.ChangeDirection(proc.Backward), t, "direction switch")
   492  				assertNoError(p.Step(), t, "reverse Step() returned an error")
   493  				assertNoError(p.ChangeDirection(proc.Forward), t, "direction switch")
   494  			case contReverseStepout:
   495  				if traceTestseq2 {
   496  					t.Log("reverse-stepout")
   497  				}
   498  				assertNoError(p.ChangeDirection(proc.Backward), t, "direction switch")
   499  				assertNoError(p.StepOut(), t, "reverse StepOut() returned an error")
   500  				assertNoError(p.ChangeDirection(proc.Forward), t, "direction switch")
   501  			case contContinueToBreakpoint:
   502  				bp := setFileBreakpoint(p, t, fixture.Source, tc.pos.(int))
   503  				if traceTestseq2 {
   504  					t.Log("continue")
   505  				}
   506  				assertNoError(p.Continue(), t, "Continue() returned an error")
   507  				err := p.ClearBreakpoint(bp.Addr)
   508  				assertNoError(err, t, "ClearBreakpoint() returned an error")
   509  			}
   510  
   511  			f, ln = currentLineNumber(p, t)
   512  			regs, _ = p.CurrentThread().Registers()
   513  			pc := regs.PC()
   514  
   515  			if traceTestseq2 {
   516  				t.Logf("at %#x %s:%d", pc, f, ln)
   517  				fmt.Printf("at %#x %s:%d\n", pc, f, ln)
   518  			}
   519  			switch pos := tc.pos.(type) {
   520  			case int:
   521  				if pos >= 0 && ln != pos {
   522  					t.Fatalf("Program did not continue to correct next location expected %d was %s:%d (%#x) (testcase %d)", pos, filepath.Base(f), ln, pc, i)
   523  				}
   524  			case string:
   525  				v := strings.Split(pos, ":")
   526  				tgtln, _ := strconv.Atoi(v[1])
   527  				if !strings.HasSuffix(f, v[0]) || (ln != tgtln) {
   528  					t.Fatalf("Program did not continue to correct next location, expected %s was %s:%d (%#x) (testcase %d)", pos, filepath.Base(f), ln, pc, i)
   529  				}
   530  			}
   531  		}
   532  
   533  		if countBreakpoints(p) != 0 {
   534  			t.Fatal("Not all breakpoints were cleaned up", len(p.Breakpoints().M))
   535  		}
   536  	})
   537  }
   538  
   539  func TestNextGeneral(t *testing.T) {
   540  	var testcases []nextTest
   541  
   542  	ver, _ := goversion.Parse(runtime.Version())
   543  
   544  	if ver.Major < 0 || ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 7, Rev: -1}) {
   545  		testcases = []nextTest{
   546  			{17, 19},
   547  			{19, 20},
   548  			{20, 23},
   549  			{23, 24},
   550  			{24, 26},
   551  			{26, 31},
   552  			{31, 23},
   553  			{23, 24},
   554  			{24, 26},
   555  			{26, 31},
   556  			{31, 23},
   557  			{23, 24},
   558  			{24, 26},
   559  			{26, 27},
   560  			{27, 28},
   561  			{28, 34},
   562  		}
   563  	} else {
   564  		testcases = []nextTest{
   565  			{17, 19},
   566  			{19, 20},
   567  			{20, 23},
   568  			{23, 24},
   569  			{24, 26},
   570  			{26, 31},
   571  			{31, 23},
   572  			{23, 24},
   573  			{24, 26},
   574  			{26, 31},
   575  			{31, 23},
   576  			{23, 24},
   577  			{24, 26},
   578  			{26, 27},
   579  			{27, 34},
   580  		}
   581  	}
   582  
   583  	testseq("testnextprog", contNext, testcases, "main.testnext", t)
   584  }
   585  
   586  func TestNextConcurrent(t *testing.T) {
   587  	skipOn(t, "broken", "freebsd")
   588  	testcases := []nextTest{
   589  		{8, 9},
   590  		{9, 10},
   591  		{10, 11},
   592  	}
   593  	protest.AllowRecording(t)
   594  	withTestProcess("parallel_next", t, func(p *proc.Target, fixture protest.Fixture) {
   595  		bp := setFunctionBreakpoint(p, t, "main.sayhi")
   596  		assertNoError(p.Continue(), t, "Continue")
   597  		f, ln := currentLineNumber(p, t)
   598  		initV := evalVariable(p, t, "n")
   599  		initVval, _ := constant.Int64Val(initV.Value)
   600  		err := p.ClearBreakpoint(bp.Addr)
   601  		assertNoError(err, t, "ClearBreakpoint()")
   602  		for _, tc := range testcases {
   603  			g, err := proc.GetG(p.CurrentThread())
   604  			assertNoError(err, t, "GetG()")
   605  			if p.SelectedGoroutine().ID != g.ID {
   606  				t.Fatalf("SelectedGoroutine not CurrentThread's goroutine: %d %d", g.ID, p.SelectedGoroutine().ID)
   607  			}
   608  			if ln != tc.begin {
   609  				t.Fatalf("Program not stopped at correct spot expected %d was %s:%d", tc.begin, filepath.Base(f), ln)
   610  			}
   611  			assertNoError(p.Next(), t, "Next() returned an error")
   612  			f, ln = assertLineNumber(p, t, tc.end, "Program did not continue to the expected location")
   613  			v := evalVariable(p, t, "n")
   614  			vval, _ := constant.Int64Val(v.Value)
   615  			if vval != initVval {
   616  				t.Fatal("Did not end up on same goroutine")
   617  			}
   618  		}
   619  	})
   620  }
   621  
   622  func TestNextConcurrentVariant2(t *testing.T) {
   623  	skipOn(t, "broken", "freebsd")
   624  	// Just like TestNextConcurrent but instead of removing the initial breakpoint we check that when it happens is for other goroutines
   625  	testcases := []nextTest{
   626  		{8, 9},
   627  		{9, 10},
   628  		{10, 11},
   629  	}
   630  	protest.AllowRecording(t)
   631  	withTestProcess("parallel_next", t, func(p *proc.Target, fixture protest.Fixture) {
   632  		setFunctionBreakpoint(p, t, "main.sayhi")
   633  		assertNoError(p.Continue(), t, "Continue")
   634  		f, ln := currentLineNumber(p, t)
   635  		initV := evalVariable(p, t, "n")
   636  		initVval, _ := constant.Int64Val(initV.Value)
   637  		for _, tc := range testcases {
   638  			t.Logf("test case %v", tc)
   639  			g, err := proc.GetG(p.CurrentThread())
   640  			assertNoError(err, t, "GetG()")
   641  			if p.SelectedGoroutine().ID != g.ID {
   642  				t.Fatalf("SelectedGoroutine not CurrentThread's goroutine: %d %d", g.ID, p.SelectedGoroutine().ID)
   643  			}
   644  			if ln != tc.begin {
   645  				t.Fatalf("Program not stopped at correct spot expected %d was %s:%d", tc.begin, filepath.Base(f), ln)
   646  			}
   647  			assertNoError(p.Next(), t, "Next() returned an error")
   648  			var vval int64
   649  			for {
   650  				v := evalVariable(p, t, "n")
   651  				for _, thread := range p.ThreadList() {
   652  					proc.GetG(thread)
   653  				}
   654  				vval, _ = constant.Int64Val(v.Value)
   655  				if bpstate := p.CurrentThread().Breakpoint(); bpstate.Breakpoint == nil {
   656  					if vval != initVval {
   657  						t.Fatal("Did not end up on same goroutine")
   658  					}
   659  					break
   660  				} else {
   661  					if vval == initVval {
   662  						t.Fatal("Initial breakpoint triggered twice for the same goroutine")
   663  					}
   664  					assertNoError(p.Continue(), t, "Continue 2")
   665  				}
   666  			}
   667  			f, ln = assertLineNumber(p, t, tc.end, "Program did not continue to the expected location")
   668  		}
   669  	})
   670  }
   671  
   672  func TestNextFunctionReturn(t *testing.T) {
   673  	testcases := []nextTest{
   674  		{13, 14},
   675  		{14, 15},
   676  		{15, 35},
   677  	}
   678  	protest.AllowRecording(t)
   679  	testseq("testnextprog", contNext, testcases, "main.helloworld", t)
   680  }
   681  
   682  func TestNextFunctionReturnDefer(t *testing.T) {
   683  	var testcases []nextTest
   684  
   685  	ver, _ := goversion.Parse(runtime.Version())
   686  
   687  	if ver.Major < 0 || ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 9, Rev: -1}) {
   688  		testcases = []nextTest{
   689  			{5, 6},
   690  			{6, 9},
   691  			{9, 10},
   692  		}
   693  	} else {
   694  		testcases = []nextTest{
   695  			{5, 8},
   696  			{8, 9},
   697  			{9, 10},
   698  		}
   699  	}
   700  	protest.AllowRecording(t)
   701  	testseq("testnextdefer", contNext, testcases, "main.main", t)
   702  }
   703  
   704  func TestNextNetHTTP(t *testing.T) {
   705  	testcases := []nextTest{
   706  		{11, 12},
   707  		{12, 13},
   708  	}
   709  	withTestProcess("testnextnethttp", t, func(p *proc.Target, fixture protest.Fixture) {
   710  		go func() {
   711  			// Wait for program to start listening.
   712  			for {
   713  				conn, err := net.Dial("tcp", "127.0.0.1:9191")
   714  				if err == nil {
   715  					conn.Close()
   716  					break
   717  				}
   718  				time.Sleep(50 * time.Millisecond)
   719  			}
   720  			http.Get("http://127.0.0.1:9191")
   721  		}()
   722  		if err := p.Continue(); err != nil {
   723  			t.Fatal(err)
   724  		}
   725  		f, ln := currentLineNumber(p, t)
   726  		for _, tc := range testcases {
   727  			if ln != tc.begin {
   728  				t.Fatalf("Program not stopped at correct spot expected %d was %s:%d", tc.begin, filepath.Base(f), ln)
   729  			}
   730  
   731  			assertNoError(p.Next(), t, "Next() returned an error")
   732  
   733  			f, ln = assertLineNumber(p, t, tc.end, "Program did not continue to correct next location")
   734  		}
   735  	})
   736  }
   737  
   738  func TestRuntimeBreakpoint(t *testing.T) {
   739  	withTestProcess("testruntimebreakpoint", t, func(p *proc.Target, fixture protest.Fixture) {
   740  		err := p.Continue()
   741  		if err != nil {
   742  			t.Fatal(err)
   743  		}
   744  		regs, err := p.CurrentThread().Registers()
   745  		assertNoError(err, t, "Registers")
   746  		pc := regs.PC()
   747  		f, l, _ := p.BinInfo().PCToLine(pc)
   748  		if l != 10 {
   749  			t.Fatalf("did not respect breakpoint %s:%d", f, l)
   750  		}
   751  	})
   752  }
   753  
   754  func returnAddress(thread proc.Thread) (uint64, error) {
   755  	locations, err := proc.ThreadStacktrace(thread, 2)
   756  	if err != nil {
   757  		return 0, err
   758  	}
   759  	if len(locations) < 2 {
   760  		return 0, fmt.Errorf("no return address for function: %s", locations[0].Current.Fn.BaseName())
   761  	}
   762  	return locations[1].Current.PC, nil
   763  }
   764  
   765  func TestFindReturnAddress(t *testing.T) {
   766  	protest.AllowRecording(t)
   767  	withTestProcess("testnextprog", t, func(p *proc.Target, fixture protest.Fixture) {
   768  		setFileBreakpoint(p, t, fixture.Source, 24)
   769  		err := p.Continue()
   770  		if err != nil {
   771  			t.Fatal(err)
   772  		}
   773  		addr, err := returnAddress(p.CurrentThread())
   774  		if err != nil {
   775  			t.Fatal(err)
   776  		}
   777  		_, l, _ := p.BinInfo().PCToLine(addr)
   778  		if l != 40 {
   779  			t.Fatalf("return address not found correctly, expected line 40")
   780  		}
   781  	})
   782  }
   783  
   784  func TestFindReturnAddressTopOfStackFn(t *testing.T) {
   785  	protest.AllowRecording(t)
   786  	withTestProcess("testreturnaddress", t, func(p *proc.Target, fixture protest.Fixture) {
   787  		fnName := "runtime.rt0_go"
   788  		setFunctionBreakpoint(p, t, fnName)
   789  		if err := p.Continue(); err != nil {
   790  			t.Fatal(err)
   791  		}
   792  		if _, err := returnAddress(p.CurrentThread()); err == nil {
   793  			t.Fatal("expected error to be returned")
   794  		}
   795  	})
   796  }
   797  
   798  func TestSwitchThread(t *testing.T) {
   799  	protest.AllowRecording(t)
   800  	withTestProcess("testnextprog", t, func(p *proc.Target, fixture protest.Fixture) {
   801  		// With invalid thread id
   802  		err := p.SwitchThread(-1)
   803  		if err == nil {
   804  			t.Fatal("Expected error for invalid thread id")
   805  		}
   806  		setFunctionBreakpoint(p, t, "main.main")
   807  		err = p.Continue()
   808  		if err != nil {
   809  			t.Fatal(err)
   810  		}
   811  		var nt int
   812  		ct := p.CurrentThread().ThreadID()
   813  		for _, thread := range p.ThreadList() {
   814  			if thread.ThreadID() != ct {
   815  				nt = thread.ThreadID()
   816  				break
   817  			}
   818  		}
   819  		if nt == 0 {
   820  			t.Fatal("could not find thread to switch to")
   821  		}
   822  		// With valid thread id
   823  		err = p.SwitchThread(nt)
   824  		if err != nil {
   825  			t.Fatal(err)
   826  		}
   827  		if p.CurrentThread().ThreadID() != nt {
   828  			t.Fatal("Did not switch threads")
   829  		}
   830  	})
   831  }
   832  
   833  func TestCGONext(t *testing.T) {
   834  	// Test if one can do 'next' in a cgo binary
   835  	// On OSX with Go < 1.5 CGO is not supported due to: https://github.com/golang/go/issues/8973
   836  	if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 5) {
   837  		skipOn(t, "upstream issue", "darwin")
   838  	}
   839  	protest.MustHaveCgo(t)
   840  
   841  	skipOn(t, "broken - cgo stacktraces", "darwin", "arm64")
   842  
   843  	protest.AllowRecording(t)
   844  	withTestProcess("cgotest", t, func(p *proc.Target, fixture protest.Fixture) {
   845  		setFunctionBreakpoint(p, t, "main.main")
   846  		assertNoError(p.Continue(), t, "Continue()")
   847  		assertNoError(p.Next(), t, "Next()")
   848  	})
   849  }
   850  
   851  type loc struct {
   852  	line int
   853  	fn   string
   854  }
   855  
   856  func (l1 *loc) match(l2 proc.Stackframe) bool {
   857  	if l1.line >= 0 {
   858  		if l1.line != l2.Call.Line {
   859  			return false
   860  		}
   861  	}
   862  	return l1.fn == l2.Call.Fn.Name
   863  }
   864  
   865  func TestStacktrace(t *testing.T) {
   866  	stacks := [][]loc{
   867  		{{4, "main.stacktraceme"}, {8, "main.func1"}, {16, "main.main"}},
   868  		{{4, "main.stacktraceme"}, {8, "main.func1"}, {12, "main.func2"}, {17, "main.main"}},
   869  	}
   870  	protest.AllowRecording(t)
   871  	withTestProcess("stacktraceprog", t, func(p *proc.Target, fixture protest.Fixture) {
   872  		bp := setFunctionBreakpoint(p, t, "main.stacktraceme")
   873  
   874  		for i := range stacks {
   875  			assertNoError(p.Continue(), t, "Continue()")
   876  			locations, err := proc.ThreadStacktrace(p.CurrentThread(), 40)
   877  			assertNoError(err, t, "Stacktrace()")
   878  
   879  			if len(locations) != len(stacks[i])+2 {
   880  				t.Fatalf("Wrong stack trace size %d %d\n", len(locations), len(stacks[i])+2)
   881  			}
   882  
   883  			t.Logf("Stacktrace %d:\n", i)
   884  			for i := range locations {
   885  				t.Logf("\t%s:%d\n", locations[i].Call.File, locations[i].Call.Line)
   886  			}
   887  
   888  			for j := range stacks[i] {
   889  				if !stacks[i][j].match(locations[j]) {
   890  					t.Fatalf("Wrong stack trace pos %d\n", j)
   891  				}
   892  			}
   893  		}
   894  
   895  		p.ClearBreakpoint(bp.Addr)
   896  		p.Continue()
   897  	})
   898  }
   899  
   900  func TestStacktrace2(t *testing.T) {
   901  	withTestProcess("retstack", t, func(p *proc.Target, fixture protest.Fixture) {
   902  		assertNoError(p.Continue(), t, "Continue()")
   903  
   904  		locations, err := proc.ThreadStacktrace(p.CurrentThread(), 40)
   905  		assertNoError(err, t, "Stacktrace()")
   906  		if !stackMatch([]loc{{-1, "main.f"}, {16, "main.main"}}, locations, false) {
   907  			for i := range locations {
   908  				t.Logf("\t%s:%d [%s]\n", locations[i].Call.File, locations[i].Call.Line, locations[i].Call.Fn.Name)
   909  			}
   910  			t.Fatalf("Stack error at main.f()\n%v\n", locations)
   911  		}
   912  
   913  		assertNoError(p.Continue(), t, "Continue()")
   914  		locations, err = proc.ThreadStacktrace(p.CurrentThread(), 40)
   915  		assertNoError(err, t, "Stacktrace()")
   916  		if !stackMatch([]loc{{-1, "main.g"}, {17, "main.main"}}, locations, false) {
   917  			for i := range locations {
   918  				t.Logf("\t%s:%d [%s]\n", locations[i].Call.File, locations[i].Call.Line, locations[i].Call.Fn.Name)
   919  			}
   920  			t.Fatalf("Stack error at main.g()\n%v\n", locations)
   921  		}
   922  	})
   923  
   924  }
   925  
   926  func stackMatch(stack []loc, locations []proc.Stackframe, skipRuntime bool) bool {
   927  	if len(stack) > len(locations) {
   928  		return false
   929  	}
   930  	i := 0
   931  	for j := range locations {
   932  		if i >= len(stack) {
   933  			break
   934  		}
   935  		if skipRuntime {
   936  			if locations[j].Call.Fn == nil || strings.HasPrefix(locations[j].Call.Fn.Name, "runtime.") {
   937  				continue
   938  			}
   939  		}
   940  		if !stack[i].match(locations[j]) {
   941  			return false
   942  		}
   943  		i++
   944  	}
   945  	return i >= len(stack)
   946  }
   947  
   948  func TestStacktraceGoroutine(t *testing.T) {
   949  	skipOn(t, "broken - cgo stacktraces", "darwin", "arm64")
   950  
   951  	mainStack := []loc{{14, "main.stacktraceme"}, {29, "main.main"}}
   952  	if goversion.VersionAfterOrEqual(runtime.Version(), 1, 11) {
   953  		mainStack[0].line = 15
   954  	}
   955  	agoroutineStacks := [][]loc{
   956  		{{8, "main.agoroutine"}},
   957  		{{9, "main.agoroutine"}},
   958  		{{10, "main.agoroutine"}},
   959  	}
   960  
   961  	lenient := 0
   962  	if runtime.GOOS == "windows" {
   963  		lenient = 1
   964  	}
   965  
   966  	protest.AllowRecording(t)
   967  	withTestProcess("goroutinestackprog", t, func(p *proc.Target, fixture protest.Fixture) {
   968  		bp := setFunctionBreakpoint(p, t, "main.stacktraceme")
   969  
   970  		assertNoError(p.Continue(), t, "Continue()")
   971  
   972  		gs, _, err := proc.GoroutinesInfo(p, 0, 0)
   973  		assertNoError(err, t, "GoroutinesInfo")
   974  
   975  		agoroutineCount := 0
   976  		mainCount := 0
   977  
   978  		for i, g := range gs {
   979  			locations, err := g.Stacktrace(40, 0)
   980  			if err != nil {
   981  				// On windows we do not have frame information for goroutines doing system calls.
   982  				t.Logf("Could not retrieve goroutine stack for goid=%d: %v", g.ID, err)
   983  				continue
   984  			}
   985  
   986  			if stackMatch(mainStack, locations, false) {
   987  				mainCount++
   988  			}
   989  
   990  			found := false
   991  			for _, agoroutineStack := range agoroutineStacks {
   992  				if stackMatch(agoroutineStack, locations, true) {
   993  					found = true
   994  				}
   995  			}
   996  
   997  			if found {
   998  				agoroutineCount++
   999  			} else {
  1000  				t.Logf("Non-goroutine stack: %d (%d)", i, len(locations))
  1001  				for i := range locations {
  1002  					name := ""
  1003  					if locations[i].Call.Fn != nil {
  1004  						name = locations[i].Call.Fn.Name
  1005  					}
  1006  					t.Logf("\t%s:%d %s (%#x) %x %v\n", locations[i].Call.File, locations[i].Call.Line, name, locations[i].Current.PC, locations[i].FrameOffset(), locations[i].SystemStack)
  1007  				}
  1008  			}
  1009  		}
  1010  
  1011  		if mainCount != 1 {
  1012  			t.Fatalf("Main goroutine stack not found %d", mainCount)
  1013  		}
  1014  
  1015  		if agoroutineCount < 10-lenient {
  1016  			t.Fatalf("Goroutine stacks not found (%d)", agoroutineCount)
  1017  		}
  1018  
  1019  		p.ClearBreakpoint(bp.Addr)
  1020  		p.Continue()
  1021  	})
  1022  }
  1023  
  1024  func TestKill(t *testing.T) {
  1025  	skipOn(t, "N/A", "lldb") // k command presumably works but leaves the process around?
  1026  	withTestProcess("testprog", t, func(p *proc.Target, fixture protest.Fixture) {
  1027  		if err := p.Detach(true); err != nil {
  1028  			t.Fatal(err)
  1029  		}
  1030  		if valid, _ := p.Valid(); valid {
  1031  			t.Fatal("expected process to have exited")
  1032  		}
  1033  		if runtime.GOOS == "linux" {
  1034  			if runtime.GOARCH == "arm64" {
  1035  				//there is no any sync between signal sended(tracee handled) and open /proc/%d/. It may fail on arm64
  1036  				return
  1037  			}
  1038  			_, err := os.Open(fmt.Sprintf("/proc/%d/", p.Pid()))
  1039  			if err == nil {
  1040  				t.Fatal("process has not exited", p.Pid())
  1041  			}
  1042  		}
  1043  	})
  1044  }
  1045  
  1046  func testGSupportFunc(name string, t *testing.T, p *proc.Target, fixture protest.Fixture) {
  1047  	bp := setFunctionBreakpoint(p, t, "main.main")
  1048  
  1049  	assertNoError(p.Continue(), t, name+": Continue()")
  1050  
  1051  	g, err := proc.GetG(p.CurrentThread())
  1052  	assertNoError(err, t, name+": GetG()")
  1053  
  1054  	if g == nil {
  1055  		t.Fatal(name + ": g was nil")
  1056  	}
  1057  
  1058  	t.Logf(name+": g is: %v", g)
  1059  
  1060  	p.ClearBreakpoint(bp.Addr)
  1061  }
  1062  
  1063  func TestGetG(t *testing.T) {
  1064  	withTestProcess("testprog", t, func(p *proc.Target, fixture protest.Fixture) {
  1065  		testGSupportFunc("nocgo", t, p, fixture)
  1066  	})
  1067  
  1068  	// On OSX with Go < 1.5 CGO is not supported due to: https://github.com/golang/go/issues/8973
  1069  	if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 5) {
  1070  		skipOn(t, "upstream issue", "darwin")
  1071  	}
  1072  	protest.MustHaveCgo(t)
  1073  
  1074  	protest.AllowRecording(t)
  1075  	withTestProcess("cgotest", t, func(p *proc.Target, fixture protest.Fixture) {
  1076  		testGSupportFunc("cgo", t, p, fixture)
  1077  	})
  1078  }
  1079  
  1080  func TestContinueMulti(t *testing.T) {
  1081  	protest.AllowRecording(t)
  1082  	withTestProcess("integrationprog", t, func(p *proc.Target, fixture protest.Fixture) {
  1083  		bp1 := setFunctionBreakpoint(p, t, "main.main")
  1084  		bp2 := setFunctionBreakpoint(p, t, "main.sayhi")
  1085  
  1086  		mainCount := 0
  1087  		sayhiCount := 0
  1088  		for {
  1089  			err := p.Continue()
  1090  			if valid, _ := p.Valid(); !valid {
  1091  				break
  1092  			}
  1093  			assertNoError(err, t, "Continue()")
  1094  
  1095  			if bp := p.CurrentThread().Breakpoint(); bp.LogicalID() == bp1.LogicalID() {
  1096  				mainCount++
  1097  			}
  1098  
  1099  			if bp := p.CurrentThread().Breakpoint(); bp.LogicalID() == bp2.LogicalID() {
  1100  				sayhiCount++
  1101  			}
  1102  		}
  1103  
  1104  		if mainCount != 1 {
  1105  			t.Fatalf("Main breakpoint hit wrong number of times: %d\n", mainCount)
  1106  		}
  1107  
  1108  		if sayhiCount != 3 {
  1109  			t.Fatalf("Sayhi breakpoint hit wrong number of times: %d\n", sayhiCount)
  1110  		}
  1111  	})
  1112  }
  1113  
  1114  func TestBreakpointOnFunctionEntry(t *testing.T) {
  1115  	testseq2(t, "testprog", "main.main", []seqTest{{contContinue, 17}})
  1116  }
  1117  
  1118  func TestProcessReceivesSIGCHLD(t *testing.T) {
  1119  	protest.AllowRecording(t)
  1120  	withTestProcess("sigchldprog", t, func(p *proc.Target, fixture protest.Fixture) {
  1121  		err := p.Continue()
  1122  		_, ok := err.(proc.ErrProcessExited)
  1123  		if !ok {
  1124  			t.Fatalf("Continue() returned unexpected error type %v", err)
  1125  		}
  1126  	})
  1127  }
  1128  
  1129  func TestIssue239(t *testing.T) {
  1130  	withTestProcess("is sue239", t, func(p *proc.Target, fixture protest.Fixture) {
  1131  		setFileBreakpoint(p, t, fixture.Source, 17)
  1132  		assertNoError(p.Continue(), t, "Continue()")
  1133  	})
  1134  }
  1135  
  1136  func findFirstNonRuntimeFrame(p *proc.Target) (proc.Stackframe, error) {
  1137  	frames, err := proc.ThreadStacktrace(p.CurrentThread(), 10)
  1138  	if err != nil {
  1139  		return proc.Stackframe{}, err
  1140  	}
  1141  
  1142  	for _, frame := range frames {
  1143  		if frame.Current.Fn != nil && !strings.HasPrefix(frame.Current.Fn.Name, "runtime.") {
  1144  			return frame, nil
  1145  		}
  1146  	}
  1147  	return proc.Stackframe{}, fmt.Errorf("non-runtime frame not found")
  1148  }
  1149  
  1150  func evalVariableOrError(p *proc.Target, symbol string) (*proc.Variable, error) {
  1151  	var scope *proc.EvalScope
  1152  	var err error
  1153  
  1154  	if testBackend == "rr" {
  1155  		var frame proc.Stackframe
  1156  		frame, err = findFirstNonRuntimeFrame(p)
  1157  		if err == nil {
  1158  			scope = proc.FrameToScope(p, p.Memory(), nil, frame)
  1159  		}
  1160  	} else {
  1161  		scope, err = proc.GoroutineScope(p, p.CurrentThread())
  1162  	}
  1163  
  1164  	if err != nil {
  1165  		return nil, err
  1166  	}
  1167  	return scope.EvalExpression(symbol, normalLoadConfig)
  1168  }
  1169  
  1170  func evalVariable(p *proc.Target, t testing.TB, symbol string) *proc.Variable {
  1171  	v, err := evalVariableOrError(p, symbol)
  1172  	if err != nil {
  1173  		_, file, line, _ := runtime.Caller(1)
  1174  		fname := filepath.Base(file)
  1175  		t.Fatalf("%s:%d: EvalVariable(%q): %v", fname, line, symbol, err)
  1176  	}
  1177  	return v
  1178  }
  1179  
  1180  func setVariable(p *proc.Target, symbol, value string) error {
  1181  	scope, err := proc.GoroutineScope(p, p.CurrentThread())
  1182  	if err != nil {
  1183  		return err
  1184  	}
  1185  	return scope.SetVariable(symbol, value)
  1186  }
  1187  
  1188  func TestVariableEvaluation(t *testing.T) {
  1189  	protest.AllowRecording(t)
  1190  	testcases := []struct {
  1191  		name        string
  1192  		st          reflect.Kind
  1193  		value       interface{}
  1194  		length, cap int64
  1195  		childrenlen int
  1196  	}{
  1197  		{"a1", reflect.String, "foofoofoofoofoofoo", 18, 0, 0},
  1198  		{"a11", reflect.Array, nil, 3, -1, 3},
  1199  		{"a12", reflect.Slice, nil, 2, 2, 2},
  1200  		{"a13", reflect.Slice, nil, 3, 3, 3},
  1201  		{"a2", reflect.Int, int64(6), 0, 0, 0},
  1202  		{"a3", reflect.Float64, float64(7.23), 0, 0, 0},
  1203  		{"a4", reflect.Array, nil, 2, -1, 2},
  1204  		{"a5", reflect.Slice, nil, 5, 5, 5},
  1205  		{"a6", reflect.Struct, nil, 2, 0, 2},
  1206  		{"a7", reflect.Ptr, nil, 1, 0, 1},
  1207  		{"a8", reflect.Struct, nil, 2, 0, 2},
  1208  		{"a9", reflect.Ptr, nil, 1, 0, 1},
  1209  		{"baz", reflect.String, "bazburzum", 9, 0, 0},
  1210  		{"neg", reflect.Int, int64(-1), 0, 0, 0},
  1211  		{"f32", reflect.Float32, float64(float32(1.2)), 0, 0, 0},
  1212  		{"c64", reflect.Complex64, complex128(complex64(1 + 2i)), 0, 0, 0},
  1213  		{"c128", reflect.Complex128, complex128(2 + 3i), 0, 0, 0},
  1214  		{"a6.Baz", reflect.Int, int64(8), 0, 0, 0},
  1215  		{"a7.Baz", reflect.Int, int64(5), 0, 0, 0},
  1216  		{"a8.Baz", reflect.String, "feh", 3, 0, 0},
  1217  		{"a8", reflect.Struct, nil, 2, 0, 2},
  1218  		{"i32", reflect.Array, nil, 2, -1, 2},
  1219  		{"b1", reflect.Bool, true, 0, 0, 0},
  1220  		{"b2", reflect.Bool, false, 0, 0, 0},
  1221  		{"f", reflect.Func, "main.barfoo", 0, 0, 0},
  1222  		{"ba", reflect.Slice, nil, 200, 200, 64},
  1223  	}
  1224  
  1225  	withTestProcess("testvariables", t, func(p *proc.Target, fixture protest.Fixture) {
  1226  		assertNoError(p.Continue(), t, "Continue() returned an error")
  1227  
  1228  		for _, tc := range testcases {
  1229  			v := evalVariable(p, t, tc.name)
  1230  
  1231  			if v.Kind != tc.st {
  1232  				t.Fatalf("%s simple type: expected: %s got: %s", tc.name, tc.st, v.Kind.String())
  1233  			}
  1234  			if v.Value == nil && tc.value != nil {
  1235  				t.Fatalf("%s value: expected: %v got: %v", tc.name, tc.value, v.Value)
  1236  			} else {
  1237  				switch v.Kind {
  1238  				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1239  					x, _ := constant.Int64Val(v.Value)
  1240  					if y, ok := tc.value.(int64); !ok || x != y {
  1241  						t.Fatalf("%s value: expected: %v got: %v", tc.name, tc.value, v.Value)
  1242  					}
  1243  				case reflect.Float32, reflect.Float64:
  1244  					x, _ := constant.Float64Val(v.Value)
  1245  					if y, ok := tc.value.(float64); !ok || x != y {
  1246  						t.Fatalf("%s value: expected: %v got: %v", tc.name, tc.value, v.Value)
  1247  					}
  1248  				case reflect.Complex64, reflect.Complex128:
  1249  					xr, _ := constant.Float64Val(constant.Real(v.Value))
  1250  					xi, _ := constant.Float64Val(constant.Imag(v.Value))
  1251  					if y, ok := tc.value.(complex128); !ok || complex(xr, xi) != y {
  1252  						t.Fatalf("%s value: expected: %v got: %v", tc.name, tc.value, v.Value)
  1253  					}
  1254  				case reflect.String:
  1255  					if y, ok := tc.value.(string); !ok || constant.StringVal(v.Value) != y {
  1256  						t.Fatalf("%s value: expected: %v got: %v", tc.name, tc.value, v.Value)
  1257  					}
  1258  				}
  1259  			}
  1260  			if v.Len != tc.length {
  1261  				t.Fatalf("%s len: expected: %d got: %d", tc.name, tc.length, v.Len)
  1262  			}
  1263  			if v.Cap != tc.cap {
  1264  				t.Fatalf("%s cap: expected: %d got: %d", tc.name, tc.cap, v.Cap)
  1265  			}
  1266  			if len(v.Children) != tc.childrenlen {
  1267  				t.Fatalf("%s children len: expected %d got: %d", tc.name, tc.childrenlen, len(v.Children))
  1268  			}
  1269  		}
  1270  	})
  1271  }
  1272  
  1273  func TestFrameEvaluation(t *testing.T) {
  1274  	protest.AllowRecording(t)
  1275  	lenient := false
  1276  	if runtime.GOOS == "windows" {
  1277  		lenient = true
  1278  	}
  1279  	withTestProcess("goroutinestackprog", t, func(p *proc.Target, fixture protest.Fixture) {
  1280  		setFunctionBreakpoint(p, t, "main.stacktraceme")
  1281  		assertNoError(p.Continue(), t, "Continue()")
  1282  
  1283  		t.Logf("stopped on thread %d, goroutine: %#v", p.CurrentThread().ThreadID(), p.SelectedGoroutine())
  1284  
  1285  		// Testing evaluation on goroutines
  1286  		gs, _, err := proc.GoroutinesInfo(p, 0, 0)
  1287  		assertNoError(err, t, "GoroutinesInfo")
  1288  		found := make([]bool, 10)
  1289  		for _, g := range gs {
  1290  			frame := -1
  1291  			frames, err := g.Stacktrace(40, 0)
  1292  			if err != nil {
  1293  				t.Logf("could not stacktrace goroutine %d: %v\n", g.ID, err)
  1294  				continue
  1295  			}
  1296  			t.Logf("Goroutine %d %#v", g.ID, g.Thread)
  1297  			logStacktrace(t, p, frames)
  1298  			for i := range frames {
  1299  				if frames[i].Call.Fn != nil && frames[i].Call.Fn.Name == "main.agoroutine" {
  1300  					frame = i
  1301  					break
  1302  				}
  1303  			}
  1304  
  1305  			if frame < 0 {
  1306  				t.Logf("Goroutine %d: could not find correct frame", g.ID)
  1307  				continue
  1308  			}
  1309  
  1310  			scope, err := proc.ConvertEvalScope(p, g.ID, frame, 0)
  1311  			assertNoError(err, t, "ConvertEvalScope()")
  1312  			t.Logf("scope = %v", scope)
  1313  			v, err := scope.EvalExpression("i", normalLoadConfig)
  1314  			t.Logf("v = %v", v)
  1315  			if err != nil {
  1316  				t.Logf("Goroutine %d: %v\n", g.ID, err)
  1317  				continue
  1318  			}
  1319  			vval, _ := constant.Int64Val(v.Value)
  1320  			found[vval] = true
  1321  		}
  1322  
  1323  		for i := range found {
  1324  			if !found[i] {
  1325  				if lenient {
  1326  					lenient = false
  1327  				} else {
  1328  					t.Fatalf("Goroutine %d not found\n", i)
  1329  				}
  1330  			}
  1331  		}
  1332  
  1333  		// Testing evaluation on frames
  1334  		assertNoError(p.Continue(), t, "Continue() 2")
  1335  		g, err := proc.GetG(p.CurrentThread())
  1336  		assertNoError(err, t, "GetG()")
  1337  
  1338  		frames, err := g.Stacktrace(40, 0)
  1339  		t.Logf("Goroutine %d %#v", g.ID, g.Thread)
  1340  		logStacktrace(t, p, frames)
  1341  
  1342  		for i := 0; i <= 3; i++ {
  1343  			scope, err := proc.ConvertEvalScope(p, g.ID, i+1, 0)
  1344  			assertNoError(err, t, fmt.Sprintf("ConvertEvalScope() on frame %d", i+1))
  1345  			v, err := scope.EvalExpression("n", normalLoadConfig)
  1346  			assertNoError(err, t, fmt.Sprintf("EvalVariable() on frame %d", i+1))
  1347  			n, _ := constant.Int64Val(v.Value)
  1348  			t.Logf("frame %d n %d\n", i+1, n)
  1349  			if n != int64(3-i) {
  1350  				t.Fatalf("On frame %d value of n is %d (not %d)", i+1, n, 3-i)
  1351  			}
  1352  		}
  1353  	})
  1354  }
  1355  
  1356  func TestThreadFrameEvaluation(t *testing.T) {
  1357  	skipOn(t, "upstream issue - https://github.com/golang/go/issues/29322", "pie")
  1358  	deadlockBp := proc.FatalThrow
  1359  	if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 11) {
  1360  		t.SkipNow()
  1361  	}
  1362  	withTestProcess("testdeadlock", t, func(p *proc.Target, fixture protest.Fixture) {
  1363  		assertNoError(p.Continue(), t, "Continue()")
  1364  
  1365  		bp := p.CurrentThread().Breakpoint()
  1366  		if bp.Breakpoint == nil || bp.Logical.Name != deadlockBp {
  1367  			t.Fatalf("did not stop at deadlock breakpoint %v", bp)
  1368  		}
  1369  
  1370  		// There is no selected goroutine during a deadlock, so the scope will
  1371  		// be a thread scope.
  1372  		scope, err := proc.ConvertEvalScope(p, 0, 0, 0)
  1373  		assertNoError(err, t, "ConvertEvalScope() on frame 0")
  1374  		_, err = scope.EvalExpression("s", normalLoadConfig)
  1375  		assertNoError(err, t, "EvalVariable(\"s\") on frame 0")
  1376  	})
  1377  }
  1378  
  1379  func TestPointerSetting(t *testing.T) {
  1380  	withTestProcess("testvariables2", t, func(p *proc.Target, fixture protest.Fixture) {
  1381  		assertNoError(p.Continue(), t, "Continue() returned an error")
  1382  
  1383  		pval := func(n int64) {
  1384  			variable := evalVariable(p, t, "p1")
  1385  			c0val, _ := constant.Int64Val(variable.Children[0].Value)
  1386  			if c0val != n {
  1387  				t.Fatalf("Wrong value of p1, *%d expected *%d", c0val, n)
  1388  			}
  1389  		}
  1390  
  1391  		pval(1)
  1392  
  1393  		// change p1 to point to i2
  1394  		scope, err := proc.GoroutineScope(p, p.CurrentThread())
  1395  		assertNoError(err, t, "Scope()")
  1396  		i2addr, err := scope.EvalExpression("i2", normalLoadConfig)
  1397  		assertNoError(err, t, "EvalExpression()")
  1398  		assertNoError(setVariable(p, "p1", fmt.Sprintf("(*int)(0x%x)", i2addr.Addr)), t, "SetVariable()")
  1399  		pval(2)
  1400  
  1401  		// change the value of i2 check that p1 also changes
  1402  		assertNoError(setVariable(p, "i2", "5"), t, "SetVariable()")
  1403  		pval(5)
  1404  	})
  1405  }
  1406  
  1407  func TestVariableFunctionScoping(t *testing.T) {
  1408  	withTestProcess("testvariables", t, func(p *proc.Target, fixture protest.Fixture) {
  1409  		err := p.Continue()
  1410  		assertNoError(err, t, "Continue() returned an error")
  1411  
  1412  		evalVariable(p, t, "a1")
  1413  		evalVariable(p, t, "a2")
  1414  
  1415  		// Move scopes, a1 exists here by a2 does not
  1416  		err = p.Continue()
  1417  		assertNoError(err, t, "Continue() returned an error")
  1418  
  1419  		evalVariable(p, t, "a1")
  1420  
  1421  		_, err = evalVariableOrError(p, "a2")
  1422  		if err == nil {
  1423  			t.Fatalf("Can eval out of scope variable a2")
  1424  		}
  1425  	})
  1426  }
  1427  
  1428  func TestRecursiveStructure(t *testing.T) {
  1429  	protest.AllowRecording(t)
  1430  	withTestProcess("testvariables2", t, func(p *proc.Target, fixture protest.Fixture) {
  1431  		assertNoError(p.Continue(), t, "Continue()")
  1432  		v := evalVariable(p, t, "aas")
  1433  		t.Logf("v: %v\n", v)
  1434  	})
  1435  }
  1436  
  1437  func TestIssue316(t *testing.T) {
  1438  	// A pointer loop that includes one interface should not send dlv into an infinite loop
  1439  	protest.AllowRecording(t)
  1440  	withTestProcess("testvariables2", t, func(p *proc.Target, fixture protest.Fixture) {
  1441  		assertNoError(p.Continue(), t, "Continue()")
  1442  		evalVariable(p, t, "iface5")
  1443  	})
  1444  }
  1445  
  1446  func TestIssue325(t *testing.T) {
  1447  	// nil pointer dereference when evaluating interfaces to function pointers
  1448  	protest.AllowRecording(t)
  1449  	withTestProcess("testvariables2", t, func(p *proc.Target, fixture protest.Fixture) {
  1450  		assertNoError(p.Continue(), t, "Continue()")
  1451  		iface2fn1v := evalVariable(p, t, "iface2fn1")
  1452  		t.Logf("iface2fn1: %v\n", iface2fn1v)
  1453  
  1454  		iface2fn2v := evalVariable(p, t, "iface2fn2")
  1455  		t.Logf("iface2fn2: %v\n", iface2fn2v)
  1456  	})
  1457  }
  1458  
  1459  func TestBreakpointCounts(t *testing.T) {
  1460  	skipOn(t, "broken", "freebsd")
  1461  	protest.AllowRecording(t)
  1462  	withTestProcess("bpcountstest", t, func(p *proc.Target, fixture protest.Fixture) {
  1463  		bp := setFileBreakpoint(p, t, fixture.Source, 12)
  1464  
  1465  		for {
  1466  			if err := p.Continue(); err != nil {
  1467  				if _, exited := err.(proc.ErrProcessExited); exited {
  1468  					break
  1469  				}
  1470  				assertNoError(err, t, "Continue()")
  1471  			}
  1472  		}
  1473  
  1474  		t.Logf("TotalHitCount: %d", bp.Logical.TotalHitCount)
  1475  		if bp.Logical.TotalHitCount != 200 {
  1476  			t.Fatalf("Wrong TotalHitCount for the breakpoint (%d)", bp.Logical.TotalHitCount)
  1477  		}
  1478  
  1479  		if len(bp.Logical.HitCount) != 2 {
  1480  			t.Fatalf("Wrong number of goroutines for breakpoint (%d)", len(bp.Logical.HitCount))
  1481  		}
  1482  
  1483  		for _, v := range bp.Logical.HitCount {
  1484  			if v != 100 {
  1485  				t.Fatalf("Wrong HitCount for breakpoint (%v)", bp.Logical.HitCount)
  1486  			}
  1487  		}
  1488  	})
  1489  }
  1490  
  1491  func TestHardcodedBreakpointCounts(t *testing.T) {
  1492  	skipOn(t, "broken", "freebsd")
  1493  	withTestProcess("hcbpcountstest", t, func(p *proc.Target, fixture protest.Fixture) {
  1494  		counts := map[int]int{}
  1495  		for {
  1496  			if err := p.Continue(); err != nil {
  1497  				if _, exited := err.(proc.ErrProcessExited); exited {
  1498  					break
  1499  				}
  1500  				assertNoError(err, t, "Continue()")
  1501  			}
  1502  
  1503  			for _, th := range p.ThreadList() {
  1504  				bp := th.Breakpoint().Breakpoint
  1505  				if bp == nil {
  1506  					continue
  1507  				}
  1508  				if bp.Logical.Name != proc.HardcodedBreakpoint {
  1509  					t.Fatalf("wrong breakpoint name %s", bp.Logical.Name)
  1510  				}
  1511  				g, err := proc.GetG(th)
  1512  				assertNoError(err, t, "GetG")
  1513  				counts[g.ID]++
  1514  			}
  1515  		}
  1516  
  1517  		if len(counts) != 2 {
  1518  			t.Fatalf("Wrong number of goroutines for hardcoded breakpoint (%d)", len(counts))
  1519  		}
  1520  
  1521  		for goid, count := range counts {
  1522  			if count != 100 {
  1523  				t.Fatalf("Wrong hit count for hardcoded breakpoint (%d) on goroutine %d", count, goid)
  1524  			}
  1525  		}
  1526  	})
  1527  }
  1528  
  1529  func BenchmarkArray(b *testing.B) {
  1530  	// each bencharr struct is 128 bytes, bencharr is 64 elements long
  1531  	b.SetBytes(int64(64 * 128))
  1532  	withTestProcess("testvariables2", b, func(p *proc.Target, fixture protest.Fixture) {
  1533  		assertNoError(p.Continue(), b, "Continue()")
  1534  		b.ResetTimer()
  1535  		for i := 0; i < b.N; i++ {
  1536  			evalVariable(p, b, "bencharr")
  1537  		}
  1538  	})
  1539  }
  1540  
  1541  const doTestBreakpointCountsWithDetection = false
  1542  
  1543  func TestBreakpointCountsWithDetection(t *testing.T) {
  1544  	if !doTestBreakpointCountsWithDetection {
  1545  		return
  1546  	}
  1547  	m := map[int64]int64{}
  1548  	protest.AllowRecording(t)
  1549  	withTestProcess("bpcountstest", t, func(p *proc.Target, fixture protest.Fixture) {
  1550  		bp := setFileBreakpoint(p, t, fixture.Source, 12)
  1551  
  1552  		for {
  1553  			if err := p.Continue(); err != nil {
  1554  				if _, exited := err.(proc.ErrProcessExited); exited {
  1555  					break
  1556  				}
  1557  				assertNoError(err, t, "Continue()")
  1558  			}
  1559  			for _, th := range p.ThreadList() {
  1560  				if bp := th.Breakpoint(); bp.Breakpoint == nil {
  1561  					continue
  1562  				}
  1563  				scope, err := proc.GoroutineScope(p, th)
  1564  				assertNoError(err, t, "Scope()")
  1565  				v, err := scope.EvalExpression("i", normalLoadConfig)
  1566  				assertNoError(err, t, "evalVariable")
  1567  				i, _ := constant.Int64Val(v.Value)
  1568  				v, err = scope.EvalExpression("id", normalLoadConfig)
  1569  				assertNoError(err, t, "evalVariable")
  1570  				id, _ := constant.Int64Val(v.Value)
  1571  				m[id] = i
  1572  			}
  1573  
  1574  			total := int64(0)
  1575  			for i := range m {
  1576  				total += m[i] + 1
  1577  			}
  1578  
  1579  			if uint64(total) != bp.Logical.TotalHitCount {
  1580  				t.Fatalf("Mismatched total count %d %d\n", total, bp.Logical.TotalHitCount)
  1581  			}
  1582  		}
  1583  
  1584  		t.Logf("TotalHitCount: %d", bp.Logical.TotalHitCount)
  1585  		if bp.Logical.TotalHitCount != 200 {
  1586  			t.Fatalf("Wrong TotalHitCount for the breakpoint (%d)", bp.Logical.TotalHitCount)
  1587  		}
  1588  
  1589  		if len(bp.Logical.HitCount) != 2 {
  1590  			t.Fatalf("Wrong number of goroutines for breakpoint (%d)", len(bp.Logical.HitCount))
  1591  		}
  1592  
  1593  		for _, v := range bp.Logical.HitCount {
  1594  			if v != 100 {
  1595  				t.Fatalf("Wrong HitCount for breakpoint (%v)", bp.Logical.HitCount)
  1596  			}
  1597  		}
  1598  	})
  1599  }
  1600  
  1601  func BenchmarkArrayPointer(b *testing.B) {
  1602  	// each bencharr struct is 128 bytes, benchparr is an array of 64 pointers to bencharr
  1603  	// each read will read 64 bencharr structs plus the 64 pointers of benchparr
  1604  	b.SetBytes(int64(64*128 + 64*8))
  1605  	withTestProcess("testvariables2", b, func(p *proc.Target, fixture protest.Fixture) {
  1606  		assertNoError(p.Continue(), b, "Continue()")
  1607  		b.ResetTimer()
  1608  		for i := 0; i < b.N; i++ {
  1609  			evalVariable(p, b, "bencharr")
  1610  		}
  1611  	})
  1612  }
  1613  
  1614  func BenchmarkMap(b *testing.B) {
  1615  	// m1 contains 41 entries, each one has a value that's 2 int values (2* 8 bytes) and a string key
  1616  	// each string key has an average of 9 character
  1617  	// reading strings and the map structure imposes a overhead that we ignore here
  1618  	b.SetBytes(int64(41 * (2*8 + 9)))
  1619  	withTestProcess("testvariables2", b, func(p *proc.Target, fixture protest.Fixture) {
  1620  		assertNoError(p.Continue(), b, "Continue()")
  1621  		b.ResetTimer()
  1622  		for i := 0; i < b.N; i++ {
  1623  			evalVariable(p, b, "m1")
  1624  		}
  1625  	})
  1626  }
  1627  
  1628  func BenchmarkGoroutinesInfo(b *testing.B) {
  1629  	withTestProcess("testvariables2", b, func(p *proc.Target, fixture protest.Fixture) {
  1630  		assertNoError(p.Continue(), b, "Continue()")
  1631  		b.ResetTimer()
  1632  		for i := 0; i < b.N; i++ {
  1633  			p.ClearCaches()
  1634  			_, _, err := proc.GoroutinesInfo(p, 0, 0)
  1635  			assertNoError(err, b, "GoroutinesInfo")
  1636  		}
  1637  	})
  1638  }
  1639  
  1640  func TestIssue262(t *testing.T) {
  1641  	// Continue does not work when the current breakpoint is set on a NOP instruction
  1642  	protest.AllowRecording(t)
  1643  	withTestProcess("issue262", t, func(p *proc.Target, fixture protest.Fixture) {
  1644  		setFileBreakpoint(p, t, fixture.Source, 11)
  1645  
  1646  		assertNoError(p.Continue(), t, "Continue()")
  1647  		err := p.Continue()
  1648  		if err == nil {
  1649  			t.Fatalf("No error on second continue")
  1650  		}
  1651  		_, exited := err.(proc.ErrProcessExited)
  1652  		if !exited {
  1653  			t.Fatalf("Process did not exit after second continue: %v", err)
  1654  		}
  1655  	})
  1656  }
  1657  
  1658  func TestIssue305(t *testing.T) {
  1659  	// If 'next' hits a breakpoint on the goroutine it's stepping through
  1660  	// the internal breakpoints aren't cleared preventing further use of
  1661  	// 'next' command
  1662  	protest.AllowRecording(t)
  1663  	withTestProcess("issue305", t, func(p *proc.Target, fixture protest.Fixture) {
  1664  		setFileBreakpoint(p, t, fixture.Source, 5)
  1665  
  1666  		assertNoError(p.Continue(), t, "Continue()")
  1667  
  1668  		assertNoError(p.Next(), t, "Next() 1")
  1669  		assertNoError(p.Next(), t, "Next() 2")
  1670  		assertNoError(p.Next(), t, "Next() 3")
  1671  		assertNoError(p.Next(), t, "Next() 4")
  1672  		assertNoError(p.Next(), t, "Next() 5")
  1673  	})
  1674  }
  1675  
  1676  func TestPointerLoops(t *testing.T) {
  1677  	// Pointer loops through map entries, pointers and slices
  1678  	// Regression test for issue #341
  1679  	protest.AllowRecording(t)
  1680  	withTestProcess("testvariables2", t, func(p *proc.Target, fixture protest.Fixture) {
  1681  		assertNoError(p.Continue(), t, "Continue()")
  1682  		for _, expr := range []string{"mapinf", "ptrinf", "sliceinf"} {
  1683  			t.Logf("requesting %s", expr)
  1684  			v := evalVariable(p, t, expr)
  1685  			t.Logf("%s: %v\n", expr, v)
  1686  		}
  1687  	})
  1688  }
  1689  
  1690  func BenchmarkLocalVariables(b *testing.B) {
  1691  	withTestProcess("testvariables", b, func(p *proc.Target, fixture protest.Fixture) {
  1692  		assertNoError(p.Continue(), b, "Continue() returned an error")
  1693  		scope, err := proc.GoroutineScope(p, p.CurrentThread())
  1694  		assertNoError(err, b, "Scope()")
  1695  		b.ResetTimer()
  1696  		for i := 0; i < b.N; i++ {
  1697  			_, err := scope.LocalVariables(normalLoadConfig)
  1698  			assertNoError(err, b, "LocalVariables()")
  1699  		}
  1700  	})
  1701  }
  1702  
  1703  func TestCondBreakpoint(t *testing.T) {
  1704  	skipOn(t, "broken", "freebsd")
  1705  	protest.AllowRecording(t)
  1706  	withTestProcess("parallel_next", t, func(p *proc.Target, fixture protest.Fixture) {
  1707  		bp := setFileBreakpoint(p, t, fixture.Source, 9)
  1708  		bp.UserBreaklet().Cond = &ast.BinaryExpr{
  1709  			Op: token.EQL,
  1710  			X:  &ast.Ident{Name: "n"},
  1711  			Y:  &ast.BasicLit{Kind: token.INT, Value: "7"},
  1712  		}
  1713  
  1714  		assertNoError(p.Continue(), t, "Continue()")
  1715  
  1716  		nvar := evalVariable(p, t, "n")
  1717  
  1718  		n, _ := constant.Int64Val(nvar.Value)
  1719  		if n != 7 {
  1720  			t.Fatalf("Stopped on wrong goroutine %d\n", n)
  1721  		}
  1722  	})
  1723  }
  1724  
  1725  func TestCondBreakpointError(t *testing.T) {
  1726  	skipOn(t, "broken", "freebsd")
  1727  	protest.AllowRecording(t)
  1728  	withTestProcess("parallel_next", t, func(p *proc.Target, fixture protest.Fixture) {
  1729  		bp := setFileBreakpoint(p, t, fixture.Source, 9)
  1730  		bp.UserBreaklet().Cond = &ast.BinaryExpr{
  1731  			Op: token.EQL,
  1732  			X:  &ast.Ident{Name: "nonexistentvariable"},
  1733  			Y:  &ast.BasicLit{Kind: token.INT, Value: "7"},
  1734  		}
  1735  
  1736  		err := p.Continue()
  1737  		if err == nil {
  1738  			t.Fatalf("No error on first Continue()")
  1739  		}
  1740  
  1741  		if err.Error() != "error evaluating expression: could not find symbol value for nonexistentvariable" && err.Error() != "multiple errors evaluating conditions" {
  1742  			t.Fatalf("Unexpected error on first Continue(): %v", err)
  1743  		}
  1744  
  1745  		bp.UserBreaklet().Cond = &ast.BinaryExpr{
  1746  			Op: token.EQL,
  1747  			X:  &ast.Ident{Name: "n"},
  1748  			Y:  &ast.BasicLit{Kind: token.INT, Value: "7"},
  1749  		}
  1750  
  1751  		err = p.Continue()
  1752  		if err != nil {
  1753  			if _, exited := err.(proc.ErrProcessExited); !exited {
  1754  				t.Fatalf("Unexpected error on second Continue(): %v", err)
  1755  			}
  1756  		} else {
  1757  			nvar := evalVariable(p, t, "n")
  1758  
  1759  			n, _ := constant.Int64Val(nvar.Value)
  1760  			if n != 7 {
  1761  				t.Fatalf("Stopped on wrong goroutine %d\n", n)
  1762  			}
  1763  		}
  1764  	})
  1765  }
  1766  
  1767  func TestHitCondBreakpointEQ(t *testing.T) {
  1768  	withTestProcess("break", t, func(p *proc.Target, fixture protest.Fixture) {
  1769  		bp := setFileBreakpoint(p, t, fixture.Source, 7)
  1770  		bp.Logical.HitCond = &struct {
  1771  			Op  token.Token
  1772  			Val int
  1773  		}{token.EQL, 3}
  1774  
  1775  		assertNoError(p.Continue(), t, "Continue()")
  1776  		ivar := evalVariable(p, t, "i")
  1777  
  1778  		i, _ := constant.Int64Val(ivar.Value)
  1779  		if i != 3 {
  1780  			t.Fatalf("Stopped on wrong hitcount %d\n", i)
  1781  		}
  1782  
  1783  		err := p.Continue()
  1784  		if _, exited := err.(proc.ErrProcessExited); !exited {
  1785  			t.Fatalf("Unexpected error on Continue(): %v", err)
  1786  		}
  1787  	})
  1788  }
  1789  
  1790  func TestHitCondBreakpointGEQ(t *testing.T) {
  1791  	protest.AllowRecording(t)
  1792  	withTestProcess("break", t, func(p *proc.Target, fixture protest.Fixture) {
  1793  		bp := setFileBreakpoint(p, t, fixture.Source, 7)
  1794  		bp.Logical.HitCond = &struct {
  1795  			Op  token.Token
  1796  			Val int
  1797  		}{token.GEQ, 3}
  1798  
  1799  		for it := 3; it <= 10; it++ {
  1800  			assertNoError(p.Continue(), t, "Continue()")
  1801  			ivar := evalVariable(p, t, "i")
  1802  
  1803  			i, _ := constant.Int64Val(ivar.Value)
  1804  			if int(i) != it {
  1805  				t.Fatalf("Stopped on wrong hitcount %d\n", i)
  1806  			}
  1807  		}
  1808  
  1809  		assertNoError(p.Continue(), t, "Continue()")
  1810  	})
  1811  }
  1812  
  1813  func TestHitCondBreakpointREM(t *testing.T) {
  1814  	protest.AllowRecording(t)
  1815  	withTestProcess("break", t, func(p *proc.Target, fixture protest.Fixture) {
  1816  		bp := setFileBreakpoint(p, t, fixture.Source, 7)
  1817  		bp.Logical.HitCond = &struct {
  1818  			Op  token.Token
  1819  			Val int
  1820  		}{token.REM, 2}
  1821  
  1822  		for it := 2; it <= 10; it += 2 {
  1823  			assertNoError(p.Continue(), t, "Continue()")
  1824  			ivar := evalVariable(p, t, "i")
  1825  
  1826  			i, _ := constant.Int64Val(ivar.Value)
  1827  			if int(i) != it {
  1828  				t.Fatalf("Stopped on wrong hitcount %d\n", i)
  1829  			}
  1830  		}
  1831  
  1832  		err := p.Continue()
  1833  		if _, exited := err.(proc.ErrProcessExited); !exited {
  1834  			t.Fatalf("Unexpected error on Continue(): %v", err)
  1835  		}
  1836  	})
  1837  }
  1838  
  1839  func TestIssue356(t *testing.T) {
  1840  	// slice with a typedef does not get printed correctly
  1841  	protest.AllowRecording(t)
  1842  	withTestProcess("testvariables2", t, func(p *proc.Target, fixture protest.Fixture) {
  1843  		assertNoError(p.Continue(), t, "Continue() returned an error")
  1844  		mmvar := evalVariable(p, t, "mainMenu")
  1845  		if mmvar.Kind != reflect.Slice {
  1846  			t.Fatalf("Wrong kind for mainMenu: %v\n", mmvar.Kind)
  1847  		}
  1848  	})
  1849  }
  1850  
  1851  func TestStepIntoFunction(t *testing.T) {
  1852  	withTestProcess("teststep", t, func(p *proc.Target, fixture protest.Fixture) {
  1853  		// Continue until breakpoint
  1854  		assertNoError(p.Continue(), t, "Continue() returned an error")
  1855  		// Step into function
  1856  		assertNoError(p.Step(), t, "Step() returned an error")
  1857  		// We should now be inside the function.
  1858  		loc, err := p.CurrentThread().Location()
  1859  		if err != nil {
  1860  			t.Fatal(err)
  1861  		}
  1862  		if loc.Fn.Name != "main.callme" {
  1863  			t.Fatalf("expected to be within the 'callme' function, was in %s instead", loc.Fn.Name)
  1864  		}
  1865  		if !strings.Contains(loc.File, "teststep") {
  1866  			t.Fatalf("debugger stopped at incorrect location: %s:%d", loc.File, loc.Line)
  1867  		}
  1868  		if loc.Line != 8 {
  1869  			t.Fatalf("debugger stopped at incorrect line: %d", loc.Line)
  1870  		}
  1871  	})
  1872  }
  1873  
  1874  func TestIssue332_Part1(t *testing.T) {
  1875  	// Next shouldn't step inside a function call
  1876  	protest.AllowRecording(t)
  1877  	withTestProcess("issue332", t, func(p *proc.Target, fixture protest.Fixture) {
  1878  		setFileBreakpoint(p, t, fixture.Source, 8)
  1879  		assertNoError(p.Continue(), t, "Continue()")
  1880  		assertNoError(p.Next(), t, "first Next()")
  1881  		locations, err := proc.ThreadStacktrace(p.CurrentThread(), 2)
  1882  		assertNoError(err, t, "Stacktrace()")
  1883  		if locations[0].Call.Fn == nil {
  1884  			t.Fatalf("Not on a function")
  1885  		}
  1886  		if locations[0].Call.Fn.Name != "main.main" {
  1887  			t.Fatalf("Not on main.main after Next: %s (%s:%d)", locations[0].Call.Fn.Name, locations[0].Call.File, locations[0].Call.Line)
  1888  		}
  1889  		if locations[0].Call.Line != 9 {
  1890  			t.Fatalf("Not on line 9 after Next: %s (%s:%d)", locations[0].Call.Fn.Name, locations[0].Call.File, locations[0].Call.Line)
  1891  		}
  1892  	})
  1893  }
  1894  
  1895  func TestIssue332_Part2(t *testing.T) {
  1896  	// Step should skip a function's prologue
  1897  	// In some parts of the prologue, for some functions, the FDE data is incorrect
  1898  	// which leads to 'next' and 'stack' failing with error "could not find FDE for PC: <garbage>"
  1899  	// because the incorrect FDE data leads to reading the wrong stack address as the return address
  1900  	protest.AllowRecording(t)
  1901  	withTestProcess("issue332", t, func(p *proc.Target, fixture protest.Fixture) {
  1902  		setFileBreakpoint(p, t, fixture.Source, 8)
  1903  		assertNoError(p.Continue(), t, "Continue()")
  1904  
  1905  		// step until we enter changeMe
  1906  		for {
  1907  			assertNoError(p.Step(), t, "Step()")
  1908  			locations, err := proc.ThreadStacktrace(p.CurrentThread(), 2)
  1909  			assertNoError(err, t, "Stacktrace()")
  1910  			if locations[0].Call.Fn == nil {
  1911  				t.Fatalf("Not on a function")
  1912  			}
  1913  			if locations[0].Call.Fn.Name == "main.changeMe" {
  1914  				break
  1915  			}
  1916  		}
  1917  
  1918  		regs, err := p.CurrentThread().Registers()
  1919  		assertNoError(err, t, "Registers()")
  1920  		pc := regs.PC()
  1921  		pcAfterPrologue := findFunctionLocation(p, t, "main.changeMe")
  1922  		if pcAfterPrologue == p.BinInfo().LookupFunc["main.changeMe"].Entry {
  1923  			t.Fatalf("main.changeMe and main.changeMe:0 are the same (%x)", pcAfterPrologue)
  1924  		}
  1925  		if pc != pcAfterPrologue {
  1926  			t.Fatalf("Step did not skip the prologue: current pc: %x, first instruction after prologue: %x", pc, pcAfterPrologue)
  1927  		}
  1928  
  1929  		assertNoError(p.Next(), t, "first Next()")
  1930  		assertNoError(p.Next(), t, "second Next()")
  1931  		assertNoError(p.Next(), t, "third Next()")
  1932  		err = p.Continue()
  1933  		if _, exited := err.(proc.ErrProcessExited); !exited {
  1934  			assertNoError(err, t, "final Continue()")
  1935  		}
  1936  	})
  1937  }
  1938  
  1939  func TestIssue414(t *testing.T) {
  1940  	skipOn(t, "broken", "linux", "386", "pie") // test occasionally hangs on linux/386/pie
  1941  	// Stepping until the program exits
  1942  	protest.AllowRecording(t)
  1943  	withTestProcess("math", t, func(p *proc.Target, fixture protest.Fixture) {
  1944  		setFileBreakpoint(p, t, fixture.Source, 9)
  1945  		assertNoError(p.Continue(), t, "Continue()")
  1946  		for {
  1947  			pc := currentPC(p, t)
  1948  			f, ln := currentLineNumber(p, t)
  1949  			t.Logf("at %s:%d %#x\n", f, ln, pc)
  1950  			var err error
  1951  			// Stepping through the runtime is not generally safe so after we are out
  1952  			// of main.main just use Next.
  1953  			// See: https://github.com/go-delve/delve/pull/2082
  1954  			if f == fixture.Source {
  1955  				err = p.Step()
  1956  			} else {
  1957  				err = p.Next()
  1958  			}
  1959  			if err != nil {
  1960  				if _, exited := err.(proc.ErrProcessExited); exited {
  1961  					break
  1962  				}
  1963  			}
  1964  			assertNoError(err, t, "Step()")
  1965  		}
  1966  	})
  1967  }
  1968  
  1969  func TestPackageVariables(t *testing.T) {
  1970  	var skippedVariable = map[string]bool{
  1971  		"runtime.uint16Eface": true,
  1972  		"runtime.uint32Eface": true,
  1973  		"runtime.uint64Eface": true,
  1974  		"runtime.stringEface": true,
  1975  		"runtime.sliceEface":  true,
  1976  	}
  1977  
  1978  	protest.AllowRecording(t)
  1979  	withTestProcess("testvariables", t, func(p *proc.Target, fixture protest.Fixture) {
  1980  		err := p.Continue()
  1981  		assertNoError(err, t, "Continue()")
  1982  		scope, err := proc.GoroutineScope(p, p.CurrentThread())
  1983  		assertNoError(err, t, "Scope()")
  1984  		vars, err := scope.PackageVariables(normalLoadConfig)
  1985  		assertNoError(err, t, "PackageVariables()")
  1986  		failed := false
  1987  		for _, v := range vars {
  1988  			if skippedVariable[v.Name] {
  1989  				continue
  1990  			}
  1991  			if v.Unreadable != nil && v.Unreadable.Error() != "no location attribute Location" {
  1992  				failed = true
  1993  				t.Logf("Unreadable variable %s: %v", v.Name, v.Unreadable)
  1994  			}
  1995  		}
  1996  		if failed {
  1997  			t.Fatalf("previous errors")
  1998  		}
  1999  	})
  2000  }
  2001  
  2002  func TestIssue149(t *testing.T) {
  2003  	ver, _ := goversion.Parse(runtime.Version())
  2004  	if ver.Major > 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 7, Rev: -1}) {
  2005  		return
  2006  	}
  2007  	// setting breakpoint on break statement
  2008  	withTestProcess("break", t, func(p *proc.Target, fixture protest.Fixture) {
  2009  		findFileLocation(p, t, fixture.Source, 8)
  2010  	})
  2011  }
  2012  
  2013  func TestPanicBreakpoint(t *testing.T) {
  2014  	protest.AllowRecording(t)
  2015  	withTestProcess("panic", t, func(p *proc.Target, fixture protest.Fixture) {
  2016  		assertNoError(p.Continue(), t, "Continue()")
  2017  		bp := p.CurrentThread().Breakpoint()
  2018  		if bp.Breakpoint == nil || bp.Logical.Name != proc.UnrecoveredPanic {
  2019  			t.Fatalf("not on unrecovered-panic breakpoint: %v", bp)
  2020  		}
  2021  	})
  2022  }
  2023  
  2024  func TestCmdLineArgs(t *testing.T) {
  2025  	expectSuccess := func(p *proc.Target, fixture protest.Fixture) {
  2026  		err := p.Continue()
  2027  		bp := p.CurrentThread().Breakpoint()
  2028  		if bp.Breakpoint != nil && bp.Logical.Name == proc.UnrecoveredPanic {
  2029  			t.Fatalf("testing args failed on unrecovered-panic breakpoint: %v", bp)
  2030  		}
  2031  		exit, exited := err.(proc.ErrProcessExited)
  2032  		if !exited {
  2033  			t.Fatalf("Process did not exit: %v", err)
  2034  		} else {
  2035  			if exit.Status != 0 {
  2036  				t.Fatalf("process exited with invalid status %d", exit.Status)
  2037  			}
  2038  		}
  2039  	}
  2040  
  2041  	expectPanic := func(p *proc.Target, fixture protest.Fixture) {
  2042  		p.Continue()
  2043  		bp := p.CurrentThread().Breakpoint()
  2044  		if bp.Breakpoint == nil || bp.Logical.Name != proc.UnrecoveredPanic {
  2045  			t.Fatalf("not on unrecovered-panic breakpoint: %v", bp)
  2046  		}
  2047  	}
  2048  
  2049  	// make sure multiple arguments (including one with spaces) are passed to the binary correctly
  2050  	withTestProcessArgs("testargs", t, ".", []string{"test"}, 0, expectSuccess)
  2051  	withTestProcessArgs("testargs", t, ".", []string{"-test"}, 0, expectPanic)
  2052  	withTestProcessArgs("testargs", t, ".", []string{"test", "pass flag"}, 0, expectSuccess)
  2053  	// check that arguments with spaces are *only* passed correctly when correctly called
  2054  	withTestProcessArgs("testargs", t, ".", []string{"test pass", "flag"}, 0, expectPanic)
  2055  	withTestProcessArgs("testargs", t, ".", []string{"test", "pass", "flag"}, 0, expectPanic)
  2056  	withTestProcessArgs("testargs", t, ".", []string{"test pass flag"}, 0, expectPanic)
  2057  	// and that invalid cases (wrong arguments or no arguments) panic
  2058  	withTestProcess("testargs", t, expectPanic)
  2059  	withTestProcessArgs("testargs", t, ".", []string{"invalid"}, 0, expectPanic)
  2060  	withTestProcessArgs("testargs", t, ".", []string{"test", "invalid"}, 0, expectPanic)
  2061  	withTestProcessArgs("testargs", t, ".", []string{"invalid", "pass flag"}, 0, expectPanic)
  2062  }
  2063  
  2064  func TestIssue462(t *testing.T) {
  2065  	skipOn(t, "broken", "windows") // Stacktrace of Goroutine 0 fails with an error
  2066  	withTestProcess("testnextnethttp", t, func(p *proc.Target, fixture protest.Fixture) {
  2067  		go func() {
  2068  			// Wait for program to start listening.
  2069  			for {
  2070  				conn, err := net.Dial("tcp", "127.0.0.1:9191")
  2071  				if err == nil {
  2072  					conn.Close()
  2073  					break
  2074  				}
  2075  				time.Sleep(50 * time.Millisecond)
  2076  			}
  2077  
  2078  			p.RequestManualStop()
  2079  		}()
  2080  
  2081  		assertNoError(p.Continue(), t, "Continue()")
  2082  		_, err := proc.ThreadStacktrace(p.CurrentThread(), 40)
  2083  		assertNoError(err, t, "Stacktrace()")
  2084  	})
  2085  }
  2086  
  2087  func TestNextParked(t *testing.T) {
  2088  	skipOn(t, "broken", "freebsd")
  2089  	protest.AllowRecording(t)
  2090  	withTestProcess("parallel_next", t, func(p *proc.Target, fixture protest.Fixture) {
  2091  		bp := setFunctionBreakpoint(p, t, "main.sayhi")
  2092  
  2093  		// continue until a parked goroutine exists
  2094  		var parkedg *proc.G
  2095  		for parkedg == nil {
  2096  			err := p.Continue()
  2097  			if _, exited := err.(proc.ErrProcessExited); exited {
  2098  				t.Log("could not find parked goroutine")
  2099  				return
  2100  			}
  2101  			assertNoError(err, t, "Continue()")
  2102  
  2103  			gs, _, err := proc.GoroutinesInfo(p, 0, 0)
  2104  			assertNoError(err, t, "GoroutinesInfo()")
  2105  
  2106  			// Search for a parked goroutine that we know for sure will have to be
  2107  			// resumed before the program can exit. This is a parked goroutine that:
  2108  			// 1. is executing main.sayhi
  2109  			// 2. hasn't called wg.Done yet
  2110  			for _, g := range gs {
  2111  				if g.Thread != nil {
  2112  					continue
  2113  				}
  2114  				frames, _ := g.Stacktrace(5, 0)
  2115  				for _, frame := range frames {
  2116  					// line 11 is the line where wg.Done is called
  2117  					if frame.Current.Fn != nil && frame.Current.Fn.Name == "main.sayhi" && frame.Current.Line < 11 {
  2118  						parkedg = g
  2119  						break
  2120  					}
  2121  				}
  2122  				if parkedg != nil {
  2123  					break
  2124  				}
  2125  			}
  2126  		}
  2127  
  2128  		assertNoError(p.SwitchGoroutine(parkedg), t, "SwitchGoroutine()")
  2129  		p.ClearBreakpoint(bp.Addr)
  2130  		assertNoError(p.Next(), t, "Next()")
  2131  
  2132  		if p.SelectedGoroutine().ID != parkedg.ID {
  2133  			t.Fatalf("Next did not continue on the selected goroutine, expected %d got %d", parkedg.ID, p.SelectedGoroutine().ID)
  2134  		}
  2135  	})
  2136  }
  2137  
  2138  func TestStepParked(t *testing.T) {
  2139  	skipOn(t, "broken", "freebsd")
  2140  	protest.AllowRecording(t)
  2141  	withTestProcess("parallel_next", t, func(p *proc.Target, fixture protest.Fixture) {
  2142  		bp := setFunctionBreakpoint(p, t, "main.sayhi")
  2143  
  2144  		// continue until a parked goroutine exists
  2145  		var parkedg *proc.G
  2146  	LookForParkedG:
  2147  		for {
  2148  			err := p.Continue()
  2149  			if _, exited := err.(proc.ErrProcessExited); exited {
  2150  				t.Log("could not find parked goroutine")
  2151  				return
  2152  			}
  2153  			assertNoError(err, t, "Continue()")
  2154  
  2155  			gs, _, err := proc.GoroutinesInfo(p, 0, 0)
  2156  			assertNoError(err, t, "GoroutinesInfo()")
  2157  
  2158  			for _, g := range gs {
  2159  				if g.Thread == nil && g.CurrentLoc.Fn != nil && g.CurrentLoc.Fn.Name == "main.sayhi" {
  2160  					parkedg = g
  2161  					break LookForParkedG
  2162  				}
  2163  			}
  2164  		}
  2165  
  2166  		t.Logf("Parked g is: %v\n", parkedg)
  2167  		frames, _ := parkedg.Stacktrace(20, 0)
  2168  		for _, frame := range frames {
  2169  			name := ""
  2170  			if frame.Call.Fn != nil {
  2171  				name = frame.Call.Fn.Name
  2172  			}
  2173  			t.Logf("\t%s:%d in %s (%#x)", frame.Call.File, frame.Call.Line, name, frame.Current.PC)
  2174  		}
  2175  
  2176  		assertNoError(p.SwitchGoroutine(parkedg), t, "SwitchGoroutine()")
  2177  		p.ClearBreakpoint(bp.Addr)
  2178  		assertNoError(p.Step(), t, "Step()")
  2179  
  2180  		if p.SelectedGoroutine().ID != parkedg.ID {
  2181  			t.Fatalf("Step did not continue on the selected goroutine, expected %d got %d", parkedg.ID, p.SelectedGoroutine().ID)
  2182  		}
  2183  	})
  2184  }
  2185  
  2186  func TestUnsupportedArch(t *testing.T) {
  2187  	ver, _ := goversion.Parse(runtime.Version())
  2188  	if ver.Major < 0 || !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 6, Rev: -1}) || ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 7, Rev: -1}) {
  2189  		// cross compile (with -N?) works only on select versions of go
  2190  		return
  2191  	}
  2192  
  2193  	fixturesDir := protest.FindFixturesDir()
  2194  	infile := filepath.Join(fixturesDir, "math.go")
  2195  	outfile := filepath.Join(fixturesDir, "_math_debug_386")
  2196  
  2197  	cmd := exec.Command("go", "build", "-gcflags=-N -l", "-o", outfile, infile)
  2198  	for _, v := range os.Environ() {
  2199  		if !strings.HasPrefix(v, "GOARCH=") {
  2200  			cmd.Env = append(cmd.Env, v)
  2201  		}
  2202  	}
  2203  	cmd.Env = append(cmd.Env, "GOARCH=386")
  2204  	out, err := cmd.CombinedOutput()
  2205  	if err != nil {
  2206  		t.Fatalf("go build failed: %v: %v", err, string(out))
  2207  	}
  2208  	defer os.Remove(outfile)
  2209  
  2210  	var p *proc.Target
  2211  
  2212  	switch testBackend {
  2213  	case "native":
  2214  		p, err = native.Launch([]string{outfile}, ".", 0, []string{}, "", [3]string{})
  2215  	case "lldb":
  2216  		p, err = gdbserial.LLDBLaunch([]string{outfile}, ".", 0, []string{}, "", [3]string{})
  2217  	default:
  2218  		t.Skip("test not valid for this backend")
  2219  	}
  2220  
  2221  	if err == nil {
  2222  		p.Detach(true)
  2223  		t.Fatal("Launch is expected to fail, but succeeded")
  2224  	}
  2225  
  2226  	if _, ok := err.(*proc.ErrUnsupportedArch); ok {
  2227  		// all good
  2228  		return
  2229  	}
  2230  
  2231  	t.Fatal(err)
  2232  }
  2233  
  2234  func TestIssue573(t *testing.T) {
  2235  	// calls to runtime.duffzero and runtime.duffcopy jump directly into the middle
  2236  	// of the function and the internal breakpoint set by StepInto may be missed.
  2237  	protest.AllowRecording(t)
  2238  	withTestProcess("issue573", t, func(p *proc.Target, fixture protest.Fixture) {
  2239  		setFunctionBreakpoint(p, t, "main.foo")
  2240  		assertNoError(p.Continue(), t, "Continue()")
  2241  		assertNoError(p.Step(), t, "Step() #1")
  2242  		assertNoError(p.Step(), t, "Step() #2") // Bug exits here.
  2243  		assertNoError(p.Step(), t, "Step() #3") // Third step ought to be possible; program ought not have exited.
  2244  	})
  2245  }
  2246  
  2247  func TestTestvariables2Prologue(t *testing.T) {
  2248  	withTestProcess("testvariables2", t, func(p *proc.Target, fixture protest.Fixture) {
  2249  		addrEntry := p.BinInfo().LookupFunc["main.main"].Entry
  2250  		addrPrologue := findFunctionLocation(p, t, "main.main")
  2251  		if addrEntry == addrPrologue {
  2252  			t.Fatalf("Prologue detection failed on testvariables2.go/main.main")
  2253  		}
  2254  	})
  2255  }
  2256  
  2257  func TestNextDeferReturnAndDirectCall(t *testing.T) {
  2258  	// Next should not step into a deferred function if it is called
  2259  	// directly, only if it is called through a panic or a deferreturn.
  2260  	// Here we test the case where the function is called by a deferreturn
  2261  	testseq("defercall", contNext, []nextTest{
  2262  		{9, 10},
  2263  		{10, 11},
  2264  		{11, 12},
  2265  		{12, 13},
  2266  		{13, 28}}, "main.callAndDeferReturn", t)
  2267  }
  2268  
  2269  func TestNextPanicAndDirectCall(t *testing.T) {
  2270  	// Next should not step into a deferred function if it is called
  2271  	// directly, only if it is called through a panic or a deferreturn.
  2272  	// Here we test the case where the function is called by a panic
  2273  	if goversion.VersionAfterOrEqual(runtime.Version(), 1, 11) {
  2274  		testseq("defercall", contNext, []nextTest{
  2275  			{15, 16},
  2276  			{16, 17},
  2277  			{17, 18},
  2278  			{18, 6}}, "main.callAndPanic2", t)
  2279  	} else {
  2280  		testseq("defercall", contNext, []nextTest{
  2281  			{15, 16},
  2282  			{16, 17},
  2283  			{17, 18},
  2284  			{18, 5}}, "main.callAndPanic2", t)
  2285  	}
  2286  }
  2287  
  2288  func TestStepCall(t *testing.T) {
  2289  	testseq("testnextprog", contStep, []nextTest{
  2290  		{34, 13},
  2291  		{13, 14}}, "", t)
  2292  }
  2293  
  2294  func TestStepCallPtr(t *testing.T) {
  2295  	// Tests that Step works correctly when calling functions with a
  2296  	// function pointer.
  2297  	if goversion.VersionAfterOrEqual(runtime.Version(), 1, 11) && !protest.RegabiSupported() {
  2298  		testseq("teststepprog", contStep, []nextTest{
  2299  			{9, 10},
  2300  			{10, 6},
  2301  			{6, 7},
  2302  			{7, 11}}, "", t)
  2303  	} else {
  2304  		testseq("teststepprog", contStep, []nextTest{
  2305  			{9, 10},
  2306  			{10, 5},
  2307  			{5, 6},
  2308  			{6, 7},
  2309  			{7, 11}}, "", t)
  2310  	}
  2311  }
  2312  
  2313  func TestStepReturnAndPanic(t *testing.T) {
  2314  	// Tests that Step works correctly when returning from functions
  2315  	// and when a deferred function is called when panic'ing.
  2316  	switch {
  2317  	case goversion.VersionAfterOrEqual(runtime.Version(), 1, 11):
  2318  		testseq("defercall", contStep, []nextTest{
  2319  			{17, 6},
  2320  			{6, 7},
  2321  			{7, 18},
  2322  			{18, 6},
  2323  			{6, 7}}, "", t)
  2324  	case goversion.VersionAfterOrEqual(runtime.Version(), 1, 10):
  2325  		testseq("defercall", contStep, []nextTest{
  2326  			{17, 5},
  2327  			{5, 6},
  2328  			{6, 7},
  2329  			{7, 18},
  2330  			{18, 5},
  2331  			{5, 6},
  2332  			{6, 7}}, "", t)
  2333  	case goversion.VersionAfterOrEqual(runtime.Version(), 1, 9):
  2334  		testseq("defercall", contStep, []nextTest{
  2335  			{17, 5},
  2336  			{5, 6},
  2337  			{6, 7},
  2338  			{7, 17},
  2339  			{17, 18},
  2340  			{18, 5},
  2341  			{5, 6},
  2342  			{6, 7}}, "", t)
  2343  	default:
  2344  		testseq("defercall", contStep, []nextTest{
  2345  			{17, 5},
  2346  			{5, 6},
  2347  			{6, 7},
  2348  			{7, 18},
  2349  			{18, 5},
  2350  			{5, 6},
  2351  			{6, 7}}, "", t)
  2352  	}
  2353  }
  2354  
  2355  func TestStepDeferReturn(t *testing.T) {
  2356  	// Tests that Step works correctly when a deferred function is
  2357  	// called during a return.
  2358  	if goversion.VersionAfterOrEqual(runtime.Version(), 1, 11) {
  2359  		testseq("defercall", contStep, []nextTest{
  2360  			{11, 6},
  2361  			{6, 7},
  2362  			{7, 12},
  2363  			{12, 13},
  2364  			{13, 6},
  2365  			{6, 7},
  2366  			{7, 13},
  2367  			{13, 28}}, "", t)
  2368  	} else {
  2369  		testseq("defercall", contStep, []nextTest{
  2370  			{11, 5},
  2371  			{5, 6},
  2372  			{6, 7},
  2373  			{7, 12},
  2374  			{12, 13},
  2375  			{13, 5},
  2376  			{5, 6},
  2377  			{6, 7},
  2378  			{7, 13},
  2379  			{13, 28}}, "", t)
  2380  	}
  2381  }
  2382  
  2383  func TestStepIgnorePrivateRuntime(t *testing.T) {
  2384  	// Tests that Step will ignore calls to private runtime functions
  2385  	// (such as runtime.convT2E in this case)
  2386  	switch {
  2387  	case goversion.VersionAfterOrEqual(runtime.Version(), 1, 17) && protest.RegabiSupported():
  2388  		testseq("teststepprog", contStep, []nextTest{
  2389  			{21, 13},
  2390  			{13, 14},
  2391  			{14, 15},
  2392  			{15, 17},
  2393  			{17, 22}}, "", t)
  2394  	case goversion.VersionAfterOrEqual(runtime.Version(), 1, 17):
  2395  		testseq("teststepprog", contStep, []nextTest{
  2396  			{21, 14},
  2397  			{14, 15},
  2398  			{15, 17},
  2399  			{17, 22}}, "", t)
  2400  	case goversion.VersionAfterOrEqual(runtime.Version(), 1, 11):
  2401  		testseq("teststepprog", contStep, []nextTest{
  2402  			{21, 14},
  2403  			{14, 15},
  2404  			{15, 22}}, "", t)
  2405  	case goversion.VersionAfterOrEqual(runtime.Version(), 1, 10):
  2406  		testseq("teststepprog", contStep, []nextTest{
  2407  			{21, 13},
  2408  			{13, 14},
  2409  			{14, 15},
  2410  			{15, 22}}, "", t)
  2411  	case goversion.VersionAfterOrEqual(runtime.Version(), 1, 7):
  2412  		testseq("teststepprog", contStep, []nextTest{
  2413  			{21, 13},
  2414  			{13, 14},
  2415  			{14, 15},
  2416  			{15, 14},
  2417  			{14, 17},
  2418  			{17, 22}}, "", t)
  2419  	default:
  2420  		testseq("teststepprog", contStep, []nextTest{
  2421  			{21, 13},
  2422  			{13, 14},
  2423  			{14, 15},
  2424  			{15, 17},
  2425  			{17, 22}}, "", t)
  2426  	}
  2427  }
  2428  
  2429  func TestIssue561(t *testing.T) {
  2430  	// Step fails to make progress when PC is at a CALL instruction
  2431  	// where a breakpoint is also set.
  2432  	protest.AllowRecording(t)
  2433  	withTestProcess("issue561", t, func(p *proc.Target, fixture protest.Fixture) {
  2434  		setFileBreakpoint(p, t, fixture.Source, 10)
  2435  		assertNoError(p.Continue(), t, "Continue()")
  2436  		assertNoError(p.Step(), t, "Step()")
  2437  		assertLineNumber(p, t, 5, "wrong line number after Step,")
  2438  	})
  2439  }
  2440  
  2441  func TestGoroutineLables(t *testing.T) {
  2442  	withTestProcess("goroutineLabels", t, func(p *proc.Target, fixture protest.Fixture) {
  2443  		assertNoError(p.Continue(), t, "Continue()")
  2444  		g, err := proc.GetG(p.CurrentThread())
  2445  		assertNoError(err, t, "GetG()")
  2446  		if len(g.Labels()) != 0 {
  2447  			t.Fatalf("No labels expected")
  2448  		}
  2449  
  2450  		assertNoError(p.Continue(), t, "Continue()")
  2451  		g, err = proc.GetG(p.CurrentThread())
  2452  		assertNoError(err, t, "GetG()")
  2453  		labels := g.Labels()
  2454  		if v := labels["k1"]; v != "v1" {
  2455  			t.Errorf("Unexpected label value k1=%v", v)
  2456  		}
  2457  		if v := labels["k2"]; v != "v2" {
  2458  			t.Errorf("Unexpected label value k2=%v", v)
  2459  		}
  2460  	})
  2461  }
  2462  
  2463  func TestStepOut(t *testing.T) {
  2464  	testseq2(t, "testnextprog", "main.helloworld", []seqTest{{contContinue, 13}, {contStepout, 35}})
  2465  }
  2466  
  2467  func TestStepConcurrentDirect(t *testing.T) {
  2468  	skipOn(t, "broken", "freebsd")
  2469  	protest.AllowRecording(t)
  2470  	withTestProcess("teststepconcurrent", t, func(p *proc.Target, fixture protest.Fixture) {
  2471  		bp := setFileBreakpoint(p, t, fixture.Source, 37)
  2472  
  2473  		assertNoError(p.Continue(), t, "Continue()")
  2474  		err := p.ClearBreakpoint(bp.Addr)
  2475  		assertNoError(err, t, "ClearBreakpoint()")
  2476  
  2477  		for _, b := range p.Breakpoints().M {
  2478  			if b.Logical.Name == proc.UnrecoveredPanic {
  2479  				err := p.ClearBreakpoint(b.Addr)
  2480  				assertNoError(err, t, "ClearBreakpoint(unrecovered-panic)")
  2481  				break
  2482  			}
  2483  		}
  2484  
  2485  		gid := p.SelectedGoroutine().ID
  2486  
  2487  		seq := []int{37, 38, 13, 15, 16, 38}
  2488  
  2489  		i := 0
  2490  		count := 0
  2491  		for {
  2492  			anyerr := false
  2493  			if p.SelectedGoroutine().ID != gid {
  2494  				t.Errorf("Step switched to different goroutine %d %d\n", gid, p.SelectedGoroutine().ID)
  2495  				anyerr = true
  2496  			}
  2497  			f, ln := currentLineNumber(p, t)
  2498  			if ln != seq[i] {
  2499  				if i == 1 && ln == 40 {
  2500  					// loop exited
  2501  					break
  2502  				}
  2503  				frames, err := proc.ThreadStacktrace(p.CurrentThread(), 20)
  2504  				if err != nil {
  2505  					t.Errorf("Could not get stacktrace of goroutine %d\n", p.SelectedGoroutine().ID)
  2506  				} else {
  2507  					t.Logf("Goroutine %d (thread: %d):", p.SelectedGoroutine().ID, p.CurrentThread().ThreadID())
  2508  					for _, frame := range frames {
  2509  						t.Logf("\t%s:%d (%#x)", frame.Call.File, frame.Call.Line, frame.Current.PC)
  2510  					}
  2511  				}
  2512  				t.Errorf("Program did not continue at expected location (%d) %s:%d [i %d count %d]", seq[i], f, ln, i, count)
  2513  				anyerr = true
  2514  			}
  2515  			if anyerr {
  2516  				t.FailNow()
  2517  			}
  2518  			i = (i + 1) % len(seq)
  2519  			if i == 0 {
  2520  				count++
  2521  			}
  2522  			assertNoError(p.Step(), t, "Step()")
  2523  		}
  2524  
  2525  		if count != 100 {
  2526  			t.Fatalf("Program did not loop expected number of times: %d", count)
  2527  		}
  2528  	})
  2529  }
  2530  
  2531  func TestStepConcurrentPtr(t *testing.T) {
  2532  	skipOn(t, "broken", "freebsd")
  2533  	protest.AllowRecording(t)
  2534  	withTestProcess("teststepconcurrent", t, func(p *proc.Target, fixture protest.Fixture) {
  2535  		setFileBreakpoint(p, t, fixture.Source, 24)
  2536  
  2537  		for _, b := range p.Breakpoints().M {
  2538  			if b.Logical.Name == proc.UnrecoveredPanic {
  2539  				err := p.ClearBreakpoint(b.Addr)
  2540  				assertNoError(err, t, "ClearBreakpoint(unrecovered-panic)")
  2541  				break
  2542  			}
  2543  		}
  2544  
  2545  		kvals := map[int]int64{}
  2546  		count := 0
  2547  		for {
  2548  			err := p.Continue()
  2549  			_, exited := err.(proc.ErrProcessExited)
  2550  			if exited {
  2551  				break
  2552  			}
  2553  			assertNoError(err, t, "Continue()")
  2554  
  2555  			f, ln := currentLineNumber(p, t)
  2556  			if ln != 24 {
  2557  				for _, th := range p.ThreadList() {
  2558  					t.Logf("thread %d stopped on breakpoint %v", th.ThreadID(), th.Breakpoint())
  2559  				}
  2560  				curbp := p.CurrentThread().Breakpoint()
  2561  				t.Fatalf("Program did not continue at expected location (24): %s:%d %#x [%v] (gid %d count %d)", f, ln, currentPC(p, t), curbp, p.SelectedGoroutine().ID, count)
  2562  			}
  2563  
  2564  			gid := p.SelectedGoroutine().ID
  2565  
  2566  			kvar := evalVariable(p, t, "k")
  2567  			k, _ := constant.Int64Val(kvar.Value)
  2568  
  2569  			if oldk, ok := kvals[gid]; ok {
  2570  				if oldk >= k {
  2571  					t.Fatalf("Goroutine %d did not make progress?", gid)
  2572  				}
  2573  			}
  2574  			kvals[gid] = k
  2575  
  2576  			assertNoError(p.Step(), t, "Step()")
  2577  			for p.Breakpoints().HasSteppingBreakpoints() {
  2578  				if p.SelectedGoroutine().ID == gid {
  2579  					t.Fatalf("step did not step into function call (but internal breakpoints still active?) (%d %d)", gid, p.SelectedGoroutine().ID)
  2580  				}
  2581  				assertNoError(p.Continue(), t, "Continue()")
  2582  			}
  2583  
  2584  			if p.SelectedGoroutine().ID != gid {
  2585  				t.Fatalf("Step switched goroutines (wanted: %d got: %d)", gid, p.SelectedGoroutine().ID)
  2586  			}
  2587  
  2588  			f, ln = assertLineNumber(p, t, 13, "Step did not step into function call")
  2589  
  2590  			count++
  2591  			if count > 50 {
  2592  				// this test could potentially go on for 10000 cycles, since that's
  2593  				// too slow we cut the execution after 50 cycles
  2594  				break
  2595  			}
  2596  		}
  2597  
  2598  		if count == 0 {
  2599  			t.Fatalf("Breakpoint never hit")
  2600  		}
  2601  	})
  2602  }
  2603  
  2604  func TestStepOutBreakpoint(t *testing.T) {
  2605  	protest.AllowRecording(t)
  2606  	withTestProcess("testnextprog", t, func(p *proc.Target, fixture protest.Fixture) {
  2607  		bp := setFileBreakpoint(p, t, fixture.Source, 13)
  2608  		assertNoError(p.Continue(), t, "Continue()")
  2609  		p.ClearBreakpoint(bp.Addr)
  2610  
  2611  		// StepOut should be interrupted by a breakpoint on the same goroutine.
  2612  		setFileBreakpoint(p, t, fixture.Source, 14)
  2613  		assertNoError(p.StepOut(), t, "StepOut()")
  2614  		assertLineNumber(p, t, 14, "wrong line number")
  2615  		if p.Breakpoints().HasSteppingBreakpoints() {
  2616  			t.Fatal("has internal breakpoints after hitting breakpoint on same goroutine")
  2617  		}
  2618  	})
  2619  }
  2620  
  2621  func TestNextBreakpoint(t *testing.T) {
  2622  	protest.AllowRecording(t)
  2623  	withTestProcess("testnextprog", t, func(p *proc.Target, fixture protest.Fixture) {
  2624  		bp := setFileBreakpoint(p, t, fixture.Source, 34)
  2625  		assertNoError(p.Continue(), t, "Continue()")
  2626  		p.ClearBreakpoint(bp.Addr)
  2627  
  2628  		// Next should be interrupted by a breakpoint on the same goroutine.
  2629  		setFileBreakpoint(p, t, fixture.Source, 14)
  2630  		assertNoError(p.Next(), t, "Next()")
  2631  		assertLineNumber(p, t, 14, "wrong line number")
  2632  		if p.Breakpoints().HasSteppingBreakpoints() {
  2633  			t.Fatal("has internal breakpoints after hitting breakpoint on same goroutine")
  2634  		}
  2635  	})
  2636  }
  2637  
  2638  func TestNextBreakpointKeepsSteppingBreakpoints(t *testing.T) {
  2639  	protest.AllowRecording(t)
  2640  	withTestProcess("testnextprog", t, func(p *proc.Target, fixture protest.Fixture) {
  2641  		p.KeepSteppingBreakpoints = proc.TracepointKeepsSteppingBreakpoints
  2642  		bp := setFileBreakpoint(p, t, fixture.Source, 34)
  2643  		assertNoError(p.Continue(), t, "Continue()")
  2644  		p.ClearBreakpoint(bp.Addr)
  2645  
  2646  		// Next should be interrupted by a tracepoint on the same goroutine.
  2647  		bp = setFileBreakpoint(p, t, fixture.Source, 14)
  2648  		bp.Logical.Tracepoint = true
  2649  		assertNoError(p.Next(), t, "Next()")
  2650  		assertLineNumber(p, t, 14, "wrong line number")
  2651  		if !p.Breakpoints().HasSteppingBreakpoints() {
  2652  			t.Fatal("does not have internal breakpoints after hitting tracepoint on same goroutine")
  2653  		}
  2654  
  2655  		// Continue to complete next.
  2656  		assertNoError(p.Continue(), t, "Continue()")
  2657  		assertLineNumber(p, t, 35, "wrong line number")
  2658  		if p.Breakpoints().HasSteppingBreakpoints() {
  2659  			t.Fatal("has internal breakpoints after completing next")
  2660  		}
  2661  	})
  2662  }
  2663  
  2664  func TestStepOutDefer(t *testing.T) {
  2665  	protest.AllowRecording(t)
  2666  	withTestProcess("testnextdefer", t, func(p *proc.Target, fixture protest.Fixture) {
  2667  		bp := setFileBreakpoint(p, t, fixture.Source, 9)
  2668  		assertNoError(p.Continue(), t, "Continue()")
  2669  		p.ClearBreakpoint(bp.Addr)
  2670  
  2671  		assertLineNumber(p, t, 9, "wrong line number")
  2672  
  2673  		assertNoError(p.StepOut(), t, "StepOut()")
  2674  
  2675  		f, l, _ := p.BinInfo().PCToLine(currentPC(p, t))
  2676  		if f == fixture.Source || l == 6 {
  2677  			t.Fatalf("wrong location %s:%d, expected to end somewhere in runtime", f, l)
  2678  		}
  2679  	})
  2680  }
  2681  
  2682  func TestStepOutDeferReturnAndDirectCall(t *testing.T) {
  2683  	// StepOut should not step into a deferred function if it is called
  2684  	// directly, only if it is called through a panic.
  2685  	// Here we test the case where the function is called by a deferreturn
  2686  	testseq2(t, "defercall", "", []seqTest{
  2687  		{contContinue, 11},
  2688  		{contStepout, 28}})
  2689  }
  2690  
  2691  func TestStepOnCallPtrInstr(t *testing.T) {
  2692  	protest.AllowRecording(t)
  2693  	withTestProcess("teststepprog", t, func(p *proc.Target, fixture protest.Fixture) {
  2694  		setFileBreakpoint(p, t, fixture.Source, 10)
  2695  
  2696  		assertNoError(p.Continue(), t, "Continue()")
  2697  
  2698  		found := false
  2699  
  2700  		for {
  2701  			_, ln := currentLineNumber(p, t)
  2702  			if ln != 10 {
  2703  				break
  2704  			}
  2705  			regs, err := p.CurrentThread().Registers()
  2706  			assertNoError(err, t, "Registers()")
  2707  			pc := regs.PC()
  2708  			text, err := proc.Disassemble(p.Memory(), regs, p.Breakpoints(), p.BinInfo(), pc, pc+uint64(p.BinInfo().Arch.MaxInstructionLength()))
  2709  			assertNoError(err, t, "Disassemble()")
  2710  			if text[0].IsCall() {
  2711  				found = true
  2712  				break
  2713  			}
  2714  			assertNoError(p.StepInstruction(), t, "StepInstruction()")
  2715  		}
  2716  
  2717  		if !found {
  2718  			t.Fatal("Could not find CALL instruction")
  2719  		}
  2720  
  2721  		assertNoError(p.Step(), t, "Step()")
  2722  
  2723  		if goversion.VersionAfterOrEqual(runtime.Version(), 1, 11) && !protest.RegabiSupported() {
  2724  			assertLineNumber(p, t, 6, "Step continued to wrong line,")
  2725  		} else {
  2726  			assertLineNumber(p, t, 5, "Step continued to wrong line,")
  2727  		}
  2728  	})
  2729  }
  2730  
  2731  func TestIssue594(t *testing.T) {
  2732  	skipOn(t, "upstream issue", "darwin", "lldb")
  2733  	// debugserver will receive an EXC_BAD_ACCESS for this, at that point
  2734  	// there is no way to reconvert this exception into a unix signal and send
  2735  	// it to the process.
  2736  	// This is a bug in debugserver/lldb:
  2737  	//  https://bugs.llvm.org//show_bug.cgi?id=22868
  2738  
  2739  	// Exceptions that aren't caused by breakpoints should be propagated
  2740  	// back to the target.
  2741  	// In particular the target should be able to cause a nil pointer
  2742  	// dereference panic and recover from it.
  2743  	protest.AllowRecording(t)
  2744  	withTestProcess("issue594", t, func(p *proc.Target, fixture protest.Fixture) {
  2745  		assertNoError(p.Continue(), t, "Continue()")
  2746  		var f string
  2747  		var ln int
  2748  		if testBackend == "rr" {
  2749  			frame, err := findFirstNonRuntimeFrame(p)
  2750  			assertNoError(err, t, "findFirstNonRuntimeFrame")
  2751  			f, ln = frame.Current.File, frame.Current.Line
  2752  		} else {
  2753  			f, ln = currentLineNumber(p, t)
  2754  		}
  2755  		if ln != 21 {
  2756  			t.Fatalf("Program stopped at %s:%d, expected :21", f, ln)
  2757  		}
  2758  	})
  2759  }
  2760  
  2761  func TestStepOutPanicAndDirectCall(t *testing.T) {
  2762  	// StepOut should not step into a deferred function if it is called
  2763  	// directly, only if it is called through a panic.
  2764  	// Here we test the case where the function is called by a panic
  2765  	if goversion.VersionAfterOrEqual(runtime.Version(), 1, 11) {
  2766  		testseq2(t, "defercall", "", []seqTest{
  2767  			{contContinue, 17},
  2768  			{contStepout, 6}})
  2769  	} else {
  2770  		testseq2(t, "defercall", "", []seqTest{
  2771  			{contContinue, 17},
  2772  			{contStepout, 5}})
  2773  	}
  2774  }
  2775  
  2776  func TestWorkDir(t *testing.T) {
  2777  	wd := os.TempDir()
  2778  	// For Darwin `os.TempDir()` returns `/tmp` which is symlink to `/private/tmp`.
  2779  	if runtime.GOOS == "darwin" {
  2780  		wd = "/private/tmp"
  2781  	}
  2782  	protest.AllowRecording(t)
  2783  	withTestProcessArgs("workdir", t, wd, []string{}, 0, func(p *proc.Target, fixture protest.Fixture) {
  2784  		setFileBreakpoint(p, t, fixture.Source, 14)
  2785  		p.Continue()
  2786  		v := evalVariable(p, t, "pwd")
  2787  		str := constant.StringVal(v.Value)
  2788  		if wd != str {
  2789  			t.Fatalf("Expected %s got %s\n", wd, str)
  2790  		}
  2791  	})
  2792  }
  2793  
  2794  func TestNegativeIntEvaluation(t *testing.T) {
  2795  	testcases := []struct {
  2796  		name  string
  2797  		typ   string
  2798  		value interface{}
  2799  	}{
  2800  		{"ni8", "int8", int64(-5)},
  2801  		{"ni16", "int16", int64(-5)},
  2802  		{"ni32", "int32", int64(-5)},
  2803  	}
  2804  	protest.AllowRecording(t)
  2805  	withTestProcess("testvariables2", t, func(p *proc.Target, fixture protest.Fixture) {
  2806  		assertNoError(p.Continue(), t, "Continue()")
  2807  		for _, tc := range testcases {
  2808  			v := evalVariable(p, t, tc.name)
  2809  			if typ := v.RealType.String(); typ != tc.typ {
  2810  				t.Fatalf("Wrong type for variable %q: %q (expected: %q)", tc.name, typ, tc.typ)
  2811  			}
  2812  			if val, _ := constant.Int64Val(v.Value); val != tc.value {
  2813  				t.Fatalf("Wrong value for variable %q: %v (expected: %v)", tc.name, val, tc.value)
  2814  			}
  2815  		}
  2816  	})
  2817  }
  2818  
  2819  func TestIssue683(t *testing.T) {
  2820  	// Step panics when source file can not be found
  2821  	protest.AllowRecording(t)
  2822  	withTestProcess("issue683", t, func(p *proc.Target, fixture protest.Fixture) {
  2823  		setFunctionBreakpoint(p, t, "main.main")
  2824  		assertNoError(p.Continue(), t, "First Continue()")
  2825  		for i := 0; i < 20; i++ {
  2826  			// eventually an error about the source file not being found will be
  2827  			// returned, the important thing is that we shouldn't panic
  2828  			err := p.Step()
  2829  			if err != nil {
  2830  				break
  2831  			}
  2832  		}
  2833  	})
  2834  }
  2835  
  2836  func TestIssue664(t *testing.T) {
  2837  	protest.AllowRecording(t)
  2838  	withTestProcess("issue664", t, func(p *proc.Target, fixture protest.Fixture) {
  2839  		setFileBreakpoint(p, t, fixture.Source, 4)
  2840  		assertNoError(p.Continue(), t, "Continue()")
  2841  		assertNoError(p.Next(), t, "Next()")
  2842  		assertLineNumber(p, t, 5, "Did not continue to correct location,")
  2843  	})
  2844  }
  2845  
  2846  // Benchmarks (*Process).Continue + (*Scope).FunctionArguments
  2847  func BenchmarkTrace(b *testing.B) {
  2848  	withTestProcess("traceperf", b, func(p *proc.Target, fixture protest.Fixture) {
  2849  		setFunctionBreakpoint(p, b, "main.PerfCheck")
  2850  		b.ResetTimer()
  2851  		for i := 0; i < b.N; i++ {
  2852  			assertNoError(p.Continue(), b, "Continue()")
  2853  			s, err := proc.GoroutineScope(p, p.CurrentThread())
  2854  			assertNoError(err, b, "Scope()")
  2855  			_, err = s.FunctionArguments(proc.LoadConfig{false, 0, 64, 0, 3, 0})
  2856  			assertNoError(err, b, "FunctionArguments()")
  2857  		}
  2858  		b.StopTimer()
  2859  	})
  2860  }
  2861  
  2862  func TestNextInDeferReturn(t *testing.T) {
  2863  	// runtime.deferreturn updates the G struct in a way that for one
  2864  	// instruction leaves the curg._defer field non-nil but with curg._defer.fn
  2865  	// field being nil.
  2866  	// We need to deal with this without panicing.
  2867  	protest.AllowRecording(t)
  2868  	withTestProcess("defercall", t, func(p *proc.Target, fixture protest.Fixture) {
  2869  		setFunctionBreakpoint(p, t, "runtime.deferreturn")
  2870  		assertNoError(p.Continue(), t, "First Continue()")
  2871  
  2872  		// Set a breakpoint on the deferred function so that the following loop
  2873  		// can not step out of the runtime.deferreturn and all the way to the
  2874  		// point where the target program panics.
  2875  		setFunctionBreakpoint(p, t, "main.sampleFunction")
  2876  		for i := 0; i < 20; i++ {
  2877  			loc, err := p.CurrentThread().Location()
  2878  			assertNoError(err, t, "CurrentThread().Location()")
  2879  			t.Logf("at %#x %s:%d", loc.PC, loc.File, loc.Line)
  2880  			if loc.Fn != nil && loc.Fn.Name == "main.sampleFunction" {
  2881  				break
  2882  			}
  2883  			assertNoError(p.Next(), t, fmt.Sprintf("Next() %d", i))
  2884  		}
  2885  	})
  2886  }
  2887  
  2888  func getg(goid int, gs []*proc.G) *proc.G {
  2889  	for _, g := range gs {
  2890  		if g.ID == goid {
  2891  			return g
  2892  		}
  2893  	}
  2894  	return nil
  2895  }
  2896  
  2897  func TestAttachDetach(t *testing.T) {
  2898  	if testBackend == "lldb" && runtime.GOOS == "linux" {
  2899  		bs, _ := ioutil.ReadFile("/proc/sys/kernel/yama/ptrace_scope")
  2900  		if bs == nil || strings.TrimSpace(string(bs)) != "0" {
  2901  			t.Logf("can not run TestAttachDetach: %v\n", bs)
  2902  			return
  2903  		}
  2904  	}
  2905  	if testBackend == "rr" {
  2906  		return
  2907  	}
  2908  	var buildFlags protest.BuildFlags
  2909  	if buildMode == "pie" {
  2910  		buildFlags |= protest.BuildModePIE
  2911  	}
  2912  	fixture := protest.BuildFixture("testnextnethttp", buildFlags)
  2913  	cmd := exec.Command(fixture.Path)
  2914  	cmd.Stdout = os.Stdout
  2915  	cmd.Stderr = os.Stderr
  2916  	assertNoError(cmd.Start(), t, "starting fixture")
  2917  
  2918  	// wait for testnextnethttp to start listening
  2919  	t0 := time.Now()
  2920  	for {
  2921  		conn, err := net.Dial("tcp", "127.0.0.1:9191")
  2922  		if err == nil {
  2923  			conn.Close()
  2924  			break
  2925  		}
  2926  		time.Sleep(50 * time.Millisecond)
  2927  		if time.Since(t0) > 10*time.Second {
  2928  			t.Fatal("fixture did not start")
  2929  		}
  2930  	}
  2931  
  2932  	var p *proc.Target
  2933  	var err error
  2934  
  2935  	switch testBackend {
  2936  	case "native":
  2937  		p, err = native.Attach(cmd.Process.Pid, []string{})
  2938  	case "lldb":
  2939  		path := ""
  2940  		if runtime.GOOS == "darwin" {
  2941  			path = fixture.Path
  2942  		}
  2943  		p, err = gdbserial.LLDBAttach(cmd.Process.Pid, path, []string{})
  2944  	default:
  2945  		err = fmt.Errorf("unknown backend %q", testBackend)
  2946  	}
  2947  
  2948  	assertNoError(err, t, "Attach")
  2949  	go func() {
  2950  		time.Sleep(1 * time.Second)
  2951  		http.Get("http://127.0.0.1:9191")
  2952  	}()
  2953  
  2954  	assertNoError(p.Continue(), t, "Continue")
  2955  	assertLineNumber(p, t, 11, "Did not continue to correct location,")
  2956  
  2957  	assertNoError(p.Detach(false), t, "Detach")
  2958  
  2959  	if runtime.GOOS != "darwin" {
  2960  		// Debugserver sometimes will leave a zombie process after detaching, this
  2961  		// seems to be a bug with debugserver.
  2962  		resp, err := http.Get("http://127.0.0.1:9191/nobp")
  2963  		assertNoError(err, t, "Page request after detach")
  2964  		bs, err := ioutil.ReadAll(resp.Body)
  2965  		assertNoError(err, t, "Reading /nobp page")
  2966  		if out := string(bs); !strings.Contains(out, "hello, world!") {
  2967  			t.Fatalf("/nobp page does not contain \"hello, world!\": %q", out)
  2968  		}
  2969  	}
  2970  
  2971  	cmd.Process.Kill()
  2972  }
  2973  
  2974  func TestVarSum(t *testing.T) {
  2975  	protest.AllowRecording(t)
  2976  	withTestProcess("testvariables2", t, func(p *proc.Target, fixture protest.Fixture) {
  2977  		assertNoError(p.Continue(), t, "Continue()")
  2978  		sumvar := evalVariable(p, t, "s1[0] + s1[1]")
  2979  		sumvarstr := constant.StringVal(sumvar.Value)
  2980  		if sumvarstr != "onetwo" {
  2981  			t.Fatalf("s1[0] + s1[1] == %q (expected \"onetwo\")", sumvarstr)
  2982  		}
  2983  		if sumvar.Len != int64(len(sumvarstr)) {
  2984  			t.Fatalf("sumvar.Len == %d (expected %d)", sumvar.Len, len(sumvarstr))
  2985  		}
  2986  	})
  2987  }
  2988  
  2989  func TestPackageWithPathVar(t *testing.T) {
  2990  	protest.AllowRecording(t)
  2991  	withTestProcess("pkgrenames", t, func(p *proc.Target, fixture protest.Fixture) {
  2992  		assertNoError(p.Continue(), t, "Continue()")
  2993  		evalVariable(p, t, "pkg.SomeVar")
  2994  		evalVariable(p, t, "pkg.SomeVar.X")
  2995  	})
  2996  }
  2997  
  2998  func TestEnvironment(t *testing.T) {
  2999  	protest.AllowRecording(t)
  3000  	os.Setenv("SOMEVAR", "bah")
  3001  	withTestProcess("testenv", t, func(p *proc.Target, fixture protest.Fixture) {
  3002  		assertNoError(p.Continue(), t, "Continue()")
  3003  		v := evalVariable(p, t, "x")
  3004  		vv := constant.StringVal(v.Value)
  3005  		t.Logf("v = %q", vv)
  3006  		if vv != "bah" {
  3007  			t.Fatalf("value of v is %q (expected \"bah\")", vv)
  3008  		}
  3009  	})
  3010  }
  3011  
  3012  func getFrameOff(p *proc.Target, t *testing.T) int64 {
  3013  	frameoffvar := evalVariable(p, t, "runtime.frameoff")
  3014  	frameoff, _ := constant.Int64Val(frameoffvar.Value)
  3015  	return frameoff
  3016  }
  3017  
  3018  func TestRecursiveNext(t *testing.T) {
  3019  	protest.AllowRecording(t)
  3020  	testcases := []nextTest{
  3021  		{6, 7},
  3022  		{7, 10},
  3023  		{10, 11},
  3024  		{11, 17},
  3025  	}
  3026  	testseq("increment", contNext, testcases, "main.Increment", t)
  3027  
  3028  	withTestProcess("increment", t, func(p *proc.Target, fixture protest.Fixture) {
  3029  		bp := setFunctionBreakpoint(p, t, "main.Increment")
  3030  		assertNoError(p.Continue(), t, "Continue")
  3031  		err := p.ClearBreakpoint(bp.Addr)
  3032  		assertNoError(err, t, "ClearBreakpoint")
  3033  		assertNoError(p.Next(), t, "Next 1")
  3034  		assertNoError(p.Next(), t, "Next 2")
  3035  		assertNoError(p.Next(), t, "Next 3")
  3036  		frameoff0 := getFrameOff(p, t)
  3037  		assertNoError(p.Step(), t, "Step")
  3038  		frameoff1 := getFrameOff(p, t)
  3039  		if frameoff0 == frameoff1 {
  3040  			t.Fatalf("did not step into function?")
  3041  		}
  3042  		assertLineNumber(p, t, 6, "program did not continue to expected location,")
  3043  		assertNoError(p.Next(), t, "Next 4")
  3044  		assertLineNumber(p, t, 7, "program did not continue to expected location,")
  3045  		assertNoError(p.StepOut(), t, "StepOut")
  3046  		assertLineNumber(p, t, 11, "program did not continue to expected location,")
  3047  		frameoff2 := getFrameOff(p, t)
  3048  		if frameoff0 != frameoff2 {
  3049  			t.Fatalf("frame offset mismatch %x != %x", frameoff0, frameoff2)
  3050  		}
  3051  	})
  3052  }
  3053  
  3054  // TestIssue877 ensures that the environment variables starting with DYLD_ and LD_
  3055  // are passed when executing the binary on OSX via debugserver
  3056  func TestIssue877(t *testing.T) {
  3057  	if runtime.GOOS != "darwin" && testBackend == "lldb" {
  3058  		return
  3059  	}
  3060  	if os.Getenv("TRAVIS") == "true" && runtime.GOOS == "darwin" {
  3061  		// Something changed on Travis side that makes the Go compiler fail if
  3062  		// DYLD_LIBRARY_PATH is set.
  3063  		t.Skip("broken")
  3064  	}
  3065  	const envval = "/usr/local/lib"
  3066  	os.Setenv("DYLD_LIBRARY_PATH", envval)
  3067  	withTestProcess("issue877", t, func(p *proc.Target, fixture protest.Fixture) {
  3068  		assertNoError(p.Continue(), t, "Continue()")
  3069  		v := evalVariable(p, t, "dyldenv")
  3070  		vv := constant.StringVal(v.Value)
  3071  		t.Logf("v = %q", vv)
  3072  		if vv != envval {
  3073  			t.Fatalf("value of v is %q (expected %q)", vv, envval)
  3074  		}
  3075  	})
  3076  }
  3077  
  3078  func TestIssue893(t *testing.T) {
  3079  	// Test what happens when next is called immediately after launching the
  3080  	// executable, acceptable behaviors are: (a) no error, (b) no source at PC
  3081  	// error, (c) program runs to completion
  3082  	protest.AllowRecording(t)
  3083  	withTestProcess("increment", t, func(p *proc.Target, fixture protest.Fixture) {
  3084  		err := p.Next()
  3085  		if err == nil {
  3086  			return
  3087  		}
  3088  		if _, ok := err.(*frame.ErrNoFDEForPC); ok {
  3089  			return
  3090  		}
  3091  		if _, ok := err.(*proc.ErrNoSourceForPC); ok {
  3092  			return
  3093  		}
  3094  		if _, ok := err.(proc.ErrProcessExited); ok {
  3095  			return
  3096  		}
  3097  		assertNoError(err, t, "Next")
  3098  	})
  3099  }
  3100  
  3101  func TestStepInstructionNoGoroutine(t *testing.T) {
  3102  	protest.AllowRecording(t)
  3103  	withTestProcess("increment", t, func(p *proc.Target, fixture protest.Fixture) {
  3104  		// Call StepInstruction immediately after launching the program, it should
  3105  		// work even though no goroutine is selected.
  3106  		assertNoError(p.StepInstruction(), t, "StepInstruction")
  3107  	})
  3108  }
  3109  
  3110  func TestIssue871(t *testing.T) {
  3111  	protest.AllowRecording(t)
  3112  	withTestProcess("issue871", t, func(p *proc.Target, fixture protest.Fixture) {
  3113  		assertNoError(p.Continue(), t, "Continue")
  3114  
  3115  		var scope *proc.EvalScope
  3116  		var err error
  3117  		if testBackend == "rr" {
  3118  			var frame proc.Stackframe
  3119  			frame, err = findFirstNonRuntimeFrame(p)
  3120  			if err == nil {
  3121  				scope = proc.FrameToScope(p, p.Memory(), nil, frame)
  3122  			}
  3123  		} else {
  3124  			scope, err = proc.GoroutineScope(p, p.CurrentThread())
  3125  		}
  3126  		assertNoError(err, t, "scope")
  3127  
  3128  		locals, err := scope.LocalVariables(normalLoadConfig)
  3129  		assertNoError(err, t, "LocalVariables")
  3130  
  3131  		foundA, foundB := false, false
  3132  
  3133  		for _, v := range locals {
  3134  			t.Logf("local %v", v)
  3135  			switch v.Name {
  3136  			case "a":
  3137  				foundA = true
  3138  				if v.Flags&proc.VariableEscaped == 0 {
  3139  					t.Errorf("variable a not flagged as escaped")
  3140  				}
  3141  			case "b":
  3142  				foundB = true
  3143  			}
  3144  		}
  3145  
  3146  		if !foundA {
  3147  			t.Errorf("variable a not found")
  3148  		}
  3149  
  3150  		if !foundB {
  3151  			t.Errorf("variable b not found")
  3152  		}
  3153  	})
  3154  }
  3155  
  3156  func TestShadowedFlag(t *testing.T) {
  3157  	if ver, _ := goversion.Parse(runtime.Version()); ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 9, Rev: -1}) {
  3158  		return
  3159  	}
  3160  	withTestProcess("testshadow", t, func(p *proc.Target, fixture protest.Fixture) {
  3161  		assertNoError(p.Continue(), t, "Continue")
  3162  		scope, err := proc.GoroutineScope(p, p.CurrentThread())
  3163  		assertNoError(err, t, "GoroutineScope")
  3164  		locals, err := scope.LocalVariables(normalLoadConfig)
  3165  		assertNoError(err, t, "LocalVariables")
  3166  		foundShadowed := false
  3167  		foundNonShadowed := false
  3168  		for _, v := range locals {
  3169  			if v.Flags&proc.VariableShadowed != 0 {
  3170  				if v.Name != "a" {
  3171  					t.Errorf("wrong shadowed variable %s", v.Name)
  3172  				}
  3173  				foundShadowed = true
  3174  				if n, _ := constant.Int64Val(v.Value); n != 0 {
  3175  					t.Errorf("wrong value for shadowed variable a: %d", n)
  3176  				}
  3177  			} else {
  3178  				if v.Name != "a" {
  3179  					t.Errorf("wrong non-shadowed variable %s", v.Name)
  3180  				}
  3181  				foundNonShadowed = true
  3182  				if n, _ := constant.Int64Val(v.Value); n != 1 {
  3183  					t.Errorf("wrong value for non-shadowed variable a: %d", n)
  3184  				}
  3185  			}
  3186  		}
  3187  		if !foundShadowed {
  3188  			t.Error("could not find any shadowed variable")
  3189  		}
  3190  		if !foundNonShadowed {
  3191  			t.Error("could not find any non-shadowed variable")
  3192  		}
  3193  	})
  3194  }
  3195  
  3196  func TestAttachStripped(t *testing.T) {
  3197  	if testBackend == "lldb" && runtime.GOOS == "linux" {
  3198  		bs, _ := ioutil.ReadFile("/proc/sys/kernel/yama/ptrace_scope")
  3199  		if bs == nil || strings.TrimSpace(string(bs)) != "0" {
  3200  			t.Logf("can not run TestAttachStripped: %v\n", bs)
  3201  			return
  3202  		}
  3203  	}
  3204  	if testBackend == "rr" {
  3205  		return
  3206  	}
  3207  	if runtime.GOOS == "darwin" {
  3208  		t.Log("-s does not produce stripped executables on macOS")
  3209  		return
  3210  	}
  3211  	if buildMode != "" {
  3212  		t.Skip("not enabled with buildmode=PIE")
  3213  	}
  3214  	fixture := protest.BuildFixture("testnextnethttp", protest.LinkStrip)
  3215  	cmd := exec.Command(fixture.Path)
  3216  	cmd.Stdout = os.Stdout
  3217  	cmd.Stderr = os.Stderr
  3218  	assertNoError(cmd.Start(), t, "starting fixture")
  3219  
  3220  	// wait for testnextnethttp to start listening
  3221  	t0 := time.Now()
  3222  	for {
  3223  		conn, err := net.Dial("tcp", "127.0.0.1:9191")
  3224  		if err == nil {
  3225  			conn.Close()
  3226  			break
  3227  		}
  3228  		time.Sleep(50 * time.Millisecond)
  3229  		if time.Since(t0) > 10*time.Second {
  3230  			t.Fatal("fixture did not start")
  3231  		}
  3232  	}
  3233  
  3234  	var p *proc.Target
  3235  	var err error
  3236  
  3237  	switch testBackend {
  3238  	case "native":
  3239  		p, err = native.Attach(cmd.Process.Pid, []string{})
  3240  	case "lldb":
  3241  		path := ""
  3242  		if runtime.GOOS == "darwin" {
  3243  			path = fixture.Path
  3244  		}
  3245  		p, err = gdbserial.LLDBAttach(cmd.Process.Pid, path, []string{})
  3246  	default:
  3247  		t.Fatalf("unknown backend %q", testBackend)
  3248  	}
  3249  
  3250  	t.Logf("error is %v", err)
  3251  
  3252  	if err == nil {
  3253  		p.Detach(true)
  3254  		t.Fatalf("expected error after attach, got nothing")
  3255  	} else {
  3256  		cmd.Process.Kill()
  3257  	}
  3258  	os.Remove(fixture.Path)
  3259  }
  3260  
  3261  func TestIssue844(t *testing.T) {
  3262  	// Conditional breakpoints should not prevent next from working if their
  3263  	// condition isn't met.
  3264  	withTestProcess("nextcond", t, func(p *proc.Target, fixture protest.Fixture) {
  3265  		setFileBreakpoint(p, t, fixture.Source, 9)
  3266  		condbp := setFileBreakpoint(p, t, fixture.Source, 10)
  3267  		condbp.UserBreaklet().Cond = &ast.BinaryExpr{
  3268  			Op: token.EQL,
  3269  			X:  &ast.Ident{Name: "n"},
  3270  			Y:  &ast.BasicLit{Kind: token.INT, Value: "11"},
  3271  		}
  3272  		assertNoError(p.Continue(), t, "Continue")
  3273  		assertNoError(p.Next(), t, "Next")
  3274  		assertLineNumber(p, t, 10, "continued to wrong location,")
  3275  	})
  3276  }
  3277  
  3278  func logStacktrace(t *testing.T, p *proc.Target, frames []proc.Stackframe) {
  3279  	for j := range frames {
  3280  		name := "?"
  3281  		if frames[j].Current.Fn != nil {
  3282  			name = frames[j].Current.Fn.Name
  3283  		}
  3284  		if frames[j].Call.Fn != nil && frames[j].Current.Fn != frames[j].Call.Fn {
  3285  			name = fmt.Sprintf("%s inlined in %s", frames[j].Call.Fn.Name, frames[j].Current.Fn.Name)
  3286  		}
  3287  
  3288  		t.Logf("\t%#x %#x %#x %s at %s:%d\n", frames[j].Call.PC, frames[j].FrameOffset(), frames[j].FramePointerOffset(), name, filepath.Base(frames[j].Call.File), frames[j].Call.Line)
  3289  		if frames[j].TopmostDefer != nil {
  3290  			_, _, fn := frames[j].TopmostDefer.DeferredFunc(p)
  3291  			fnname := ""
  3292  			if fn != nil {
  3293  				fnname = fn.Name
  3294  			}
  3295  			t.Logf("\t\ttopmost defer: %#x %s\n", frames[j].TopmostDefer.DwrapPC, fnname)
  3296  		}
  3297  		for deferIdx, _defer := range frames[j].Defers {
  3298  			_, _, fn := _defer.DeferredFunc(p)
  3299  			fnname := ""
  3300  			if fn != nil {
  3301  				fnname = fn.Name
  3302  			}
  3303  			t.Logf("\t\t%d defer: %#x %s\n", deferIdx, _defer.DwrapPC, fnname)
  3304  
  3305  		}
  3306  	}
  3307  }
  3308  
  3309  // stacktraceCheck checks that all the functions listed in tc appear in
  3310  // frames in the same order.
  3311  // Checks that all the functions in tc starting with "C." or with "!" are in
  3312  // a systemstack frame.
  3313  // Returns a slice m where m[i] is the index in frames of the function tc[i]
  3314  // or nil if any check fails.
  3315  func stacktraceCheck(t *testing.T, tc []string, frames []proc.Stackframe) []int {
  3316  	m := make([]int, len(tc))
  3317  	i, j := 0, 0
  3318  	for i < len(tc) {
  3319  		tcname := tc[i]
  3320  		tcsystem := strings.HasPrefix(tcname, "C.")
  3321  		if tcname[0] == '!' {
  3322  			tcsystem = true
  3323  			tcname = tcname[1:]
  3324  		}
  3325  		for j < len(frames) {
  3326  			name := "?"
  3327  			if frames[j].Current.Fn != nil {
  3328  				name = frames[j].Current.Fn.Name
  3329  			}
  3330  			if name == tcname {
  3331  				m[i] = j
  3332  				if tcsystem != frames[j].SystemStack {
  3333  					t.Logf("system stack check failed for frame %d (expected %v got %v)", j, tcsystem, frames[j].SystemStack)
  3334  					t.Logf("expected: %v\n", tc)
  3335  					return nil
  3336  				}
  3337  				break
  3338  			}
  3339  
  3340  			j++
  3341  		}
  3342  		if j >= len(frames) {
  3343  			t.Logf("couldn't find frame %d %s", i, tc)
  3344  			t.Logf("expected: %v\n", tc)
  3345  			return nil
  3346  		}
  3347  
  3348  		i++
  3349  	}
  3350  	return m
  3351  }
  3352  
  3353  func frameInFile(frame proc.Stackframe, file string) bool {
  3354  	for _, loc := range []proc.Location{frame.Current, frame.Call} {
  3355  		if !strings.HasSuffix(loc.File, file) && !strings.HasSuffix(loc.File, "/"+file) && !strings.HasSuffix(loc.File, "\\"+file) {
  3356  			return false
  3357  		}
  3358  		if loc.Line <= 0 {
  3359  			return false
  3360  		}
  3361  	}
  3362  	return true
  3363  }
  3364  
  3365  func TestCgoStacktrace(t *testing.T) {
  3366  	if runtime.GOOS == "windows" {
  3367  		ver, _ := goversion.Parse(runtime.Version())
  3368  		if ver.Major > 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 9, Rev: -1}) {
  3369  			t.Skip("disabled on windows with go before version 1.9")
  3370  		}
  3371  	}
  3372  	if runtime.GOOS == "darwin" {
  3373  		ver, _ := goversion.Parse(runtime.Version())
  3374  		if ver.Major > 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 8, Rev: -1}) {
  3375  			t.Skip("disabled on macOS with go before version 1.8")
  3376  		}
  3377  	}
  3378  
  3379  	skipOn(t, "broken - cgo stacktraces", "386")
  3380  	skipOn(t, "broken - cgo stacktraces", "linux", "arm64")
  3381  	protest.MustHaveCgo(t)
  3382  
  3383  	// Tests that:
  3384  	// a) we correctly identify the goroutine while we are executing cgo code
  3385  	// b) that we can stitch together the system stack (where cgo code
  3386  	// executes) and the normal goroutine stack
  3387  
  3388  	// Each test case describes how the stack trace should appear after a
  3389  	// continue. The first function on each test case is the topmost function
  3390  	// that should be found on the stack, the actual stack trace can have more
  3391  	// frame than those listed here but all the frames listed must appear in
  3392  	// the specified order.
  3393  	testCases := [][]string{
  3394  		[]string{"main.main"},
  3395  		[]string{"C.helloworld_pt2", "C.helloworld", "main.main"},
  3396  		[]string{"main.helloWorldS", "main.helloWorld", "C.helloworld_pt2", "C.helloworld", "main.main"},
  3397  		[]string{"C.helloworld_pt4", "C.helloworld_pt3", "main.helloWorldS", "main.helloWorld", "C.helloworld_pt2", "C.helloworld", "main.main"},
  3398  		[]string{"main.helloWorld2", "C.helloworld_pt4", "C.helloworld_pt3", "main.helloWorldS", "main.helloWorld", "C.helloworld_pt2", "C.helloworld", "main.main"}}
  3399  
  3400  	var gid int
  3401  
  3402  	frameOffs := map[string]int64{}
  3403  	framePointerOffs := map[string]int64{}
  3404  
  3405  	withTestProcess("cgostacktest/", t, func(p *proc.Target, fixture protest.Fixture) {
  3406  		for itidx, tc := range testCases {
  3407  			assertNoError(p.Continue(), t, fmt.Sprintf("Continue at iteration step %d", itidx))
  3408  
  3409  			g, err := proc.GetG(p.CurrentThread())
  3410  			assertNoError(err, t, fmt.Sprintf("GetG at iteration step %d", itidx))
  3411  
  3412  			if itidx == 0 {
  3413  				gid = g.ID
  3414  			} else {
  3415  				if gid != g.ID {
  3416  					t.Fatalf("wrong goroutine id at iteration step %d (expected %d got %d)", itidx, gid, g.ID)
  3417  				}
  3418  			}
  3419  
  3420  			frames, err := g.Stacktrace(100, 0)
  3421  			assertNoError(err, t, fmt.Sprintf("Stacktrace at iteration step %d", itidx))
  3422  
  3423  			t.Logf("iteration step %d", itidx)
  3424  			logStacktrace(t, p, frames)
  3425  
  3426  			m := stacktraceCheck(t, tc, frames)
  3427  			mismatch := (m == nil)
  3428  
  3429  			for i, j := range m {
  3430  				if strings.HasPrefix(tc[i], "C.hellow") {
  3431  					if !frameInFile(frames[j], "hello.c") {
  3432  						t.Logf("position in %q is %s:%d (call %s:%d)", tc[i], frames[j].Current.File, frames[j].Current.Line, frames[j].Call.File, frames[j].Call.Line)
  3433  						mismatch = true
  3434  						break
  3435  					}
  3436  				}
  3437  				if frameOff, ok := frameOffs[tc[i]]; ok {
  3438  					if frameOff != frames[j].FrameOffset() {
  3439  						t.Logf("frame %s offset mismatch", tc[i])
  3440  					}
  3441  					if framePointerOffs[tc[i]] != frames[j].FramePointerOffset() {
  3442  						t.Logf("frame %s pointer offset mismatch", tc[i])
  3443  					}
  3444  				} else {
  3445  					frameOffs[tc[i]] = frames[j].FrameOffset()
  3446  					framePointerOffs[tc[i]] = frames[j].FramePointerOffset()
  3447  				}
  3448  			}
  3449  
  3450  			// also check that ThreadStacktrace produces the same list of frames
  3451  			threadFrames, err := proc.ThreadStacktrace(p.CurrentThread(), 100)
  3452  			assertNoError(err, t, fmt.Sprintf("ThreadStacktrace at iteration step %d", itidx))
  3453  
  3454  			if len(threadFrames) != len(frames) {
  3455  				mismatch = true
  3456  			} else {
  3457  				for j := range frames {
  3458  					if frames[j].Current.File != threadFrames[j].Current.File || frames[j].Current.Line != threadFrames[j].Current.Line {
  3459  						t.Logf("stack mismatch between goroutine stacktrace and thread stacktrace")
  3460  						t.Logf("thread stacktrace:")
  3461  						logStacktrace(t, p, threadFrames)
  3462  						mismatch = true
  3463  						break
  3464  					}
  3465  				}
  3466  			}
  3467  			if mismatch {
  3468  				t.Fatal("see previous loglines")
  3469  			}
  3470  		}
  3471  	})
  3472  }
  3473  
  3474  func TestCgoSources(t *testing.T) {
  3475  	if runtime.GOOS == "windows" {
  3476  		ver, _ := goversion.Parse(runtime.Version())
  3477  		if ver.Major > 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 9, Rev: -1}) {
  3478  			t.Skip("disabled on windows with go before version 1.9")
  3479  		}
  3480  	}
  3481  
  3482  	if runtime.GOARCH == "386" {
  3483  		t.Skip("cgo stacktraces not supported on i386 for now")
  3484  	}
  3485  
  3486  	protest.MustHaveCgo(t)
  3487  
  3488  	withTestProcess("cgostacktest/", t, func(p *proc.Target, fixture protest.Fixture) {
  3489  		sources := p.BinInfo().Sources
  3490  		for _, needle := range []string{"main.go", "hello.c"} {
  3491  			found := false
  3492  			for _, k := range sources {
  3493  				if strings.HasSuffix(k, needle) || strings.HasSuffix(k, "/"+needle) || strings.HasSuffix(k, "\\"+needle) {
  3494  					found = true
  3495  					break
  3496  				}
  3497  			}
  3498  			if !found {
  3499  				t.Errorf("File %s not found", needle)
  3500  			}
  3501  		}
  3502  	})
  3503  }
  3504  
  3505  func TestSystemstackStacktrace(t *testing.T) {
  3506  	// check that we can follow a stack switch initiated by runtime.systemstack()
  3507  	withTestProcess("panic", t, func(p *proc.Target, fixture protest.Fixture) {
  3508  		setFunctionBreakpoint(p, t, "runtime.startpanic_m")
  3509  		assertNoError(p.Continue(), t, "first continue")
  3510  		assertNoError(p.Continue(), t, "second continue")
  3511  		g, err := proc.GetG(p.CurrentThread())
  3512  		assertNoError(err, t, "GetG")
  3513  		frames, err := g.Stacktrace(100, 0)
  3514  		assertNoError(err, t, "stacktrace")
  3515  		logStacktrace(t, p, frames)
  3516  		m := stacktraceCheck(t, []string{"!runtime.startpanic_m", "runtime.gopanic", "main.main"}, frames)
  3517  		if m == nil {
  3518  			t.Fatal("see previous loglines")
  3519  		}
  3520  	})
  3521  }
  3522  
  3523  func TestSystemstackOnRuntimeNewstack(t *testing.T) {
  3524  	// The bug being tested here manifests as follows:
  3525  	// - set a breakpoint somewhere or interrupt the program with Ctrl-C
  3526  	// - try to look at stacktraces of other goroutines
  3527  	// If one of the other goroutines is resizing its own stack the stack
  3528  	// command won't work for it.
  3529  	withTestProcess("binarytrees", t, func(p *proc.Target, fixture protest.Fixture) {
  3530  		setFunctionBreakpoint(p, t, "main.main")
  3531  		assertNoError(p.Continue(), t, "first continue")
  3532  
  3533  		g, err := proc.GetG(p.CurrentThread())
  3534  		assertNoError(err, t, "GetG")
  3535  		mainGoroutineID := g.ID
  3536  
  3537  		setFunctionBreakpoint(p, t, "runtime.newstack")
  3538  		for {
  3539  			assertNoError(p.Continue(), t, "second continue")
  3540  			g, err = proc.GetG(p.CurrentThread())
  3541  			assertNoError(err, t, "GetG")
  3542  			if g.ID == mainGoroutineID {
  3543  				break
  3544  			}
  3545  		}
  3546  		frames, err := g.Stacktrace(100, 0)
  3547  		assertNoError(err, t, "stacktrace")
  3548  		logStacktrace(t, p, frames)
  3549  		m := stacktraceCheck(t, []string{"!runtime.newstack", "main.main"}, frames)
  3550  		if m == nil {
  3551  			t.Fatal("see previous loglines")
  3552  		}
  3553  	})
  3554  }
  3555  
  3556  func TestIssue1034(t *testing.T) {
  3557  	skipOn(t, "broken - cgo stacktraces", "386")
  3558  	protest.MustHaveCgo(t)
  3559  
  3560  	// The external linker on macOS produces an abbrev for DW_TAG_subprogram
  3561  	// without the "has children" flag, we should support this.
  3562  	withTestProcess("cgostacktest/", t, func(p *proc.Target, fixture protest.Fixture) {
  3563  		setFunctionBreakpoint(p, t, "main.main")
  3564  		assertNoError(p.Continue(), t, "Continue()")
  3565  		frames, err := p.SelectedGoroutine().Stacktrace(10, 0)
  3566  		assertNoError(err, t, "Stacktrace")
  3567  		scope := proc.FrameToScope(p, p.Memory(), nil, frames[2:]...)
  3568  		args, _ := scope.FunctionArguments(normalLoadConfig)
  3569  		assertNoError(err, t, "FunctionArguments()")
  3570  		if len(args) > 0 {
  3571  			t.Fatalf("wrong number of arguments for frame %v (%d)", frames[2], len(args))
  3572  		}
  3573  	})
  3574  }
  3575  
  3576  func TestIssue1008(t *testing.T) {
  3577  	skipOn(t, "broken - cgo stacktraces", "386")
  3578  	protest.MustHaveCgo(t)
  3579  
  3580  	// The external linker on macOS inserts "end of sequence" extended opcodes
  3581  	// in debug_line. which we should support correctly.
  3582  	withTestProcess("cgostacktest/", t, func(p *proc.Target, fixture protest.Fixture) {
  3583  		setFunctionBreakpoint(p, t, "main.main")
  3584  		assertNoError(p.Continue(), t, "Continue()")
  3585  		loc, err := p.CurrentThread().Location()
  3586  		assertNoError(err, t, "CurrentThread().Location()")
  3587  		t.Logf("location %v\n", loc)
  3588  		if !strings.HasSuffix(loc.File, "/main.go") {
  3589  			t.Errorf("unexpected location %s:%d\n", loc.File, loc.Line)
  3590  		}
  3591  		if loc.Line > 31 {
  3592  			t.Errorf("unexpected location %s:%d (file only has 30 lines)\n", loc.File, loc.Line)
  3593  		}
  3594  	})
  3595  }
  3596  
  3597  func testDeclLineCount(t *testing.T, p *proc.Target, lineno int, tgtvars []string) {
  3598  	sort.Strings(tgtvars)
  3599  
  3600  	assertLineNumber(p, t, lineno, "Program did not continue to correct next location")
  3601  	scope, err := proc.GoroutineScope(p, p.CurrentThread())
  3602  	assertNoError(err, t, fmt.Sprintf("GoroutineScope (:%d)", lineno))
  3603  	vars, err := scope.Locals(0)
  3604  	assertNoError(err, t, fmt.Sprintf("Locals (:%d)", lineno))
  3605  	if len(vars) != len(tgtvars) {
  3606  		t.Fatalf("wrong number of variables %d (:%d)", len(vars), lineno)
  3607  	}
  3608  	outvars := make([]string, len(vars))
  3609  	for i, v := range vars {
  3610  		outvars[i] = v.Name
  3611  	}
  3612  	sort.Strings(outvars)
  3613  
  3614  	for i := range outvars {
  3615  		if tgtvars[i] != outvars[i] {
  3616  			t.Fatalf("wrong variables, got: %q expected %q\n", outvars, tgtvars)
  3617  		}
  3618  	}
  3619  }
  3620  
  3621  func TestDeclLine(t *testing.T) {
  3622  	ver, _ := goversion.Parse(runtime.Version())
  3623  	if ver.Major > 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}) {
  3624  		t.Skip("go 1.9 and prior versions do not emit DW_AT_decl_line")
  3625  	}
  3626  
  3627  	withTestProcess("decllinetest", t, func(p *proc.Target, fixture protest.Fixture) {
  3628  		setFileBreakpoint(p, t, fixture.Source, 8)
  3629  		setFileBreakpoint(p, t, fixture.Source, 9)
  3630  		setFileBreakpoint(p, t, fixture.Source, 10)
  3631  		setFileBreakpoint(p, t, fixture.Source, 11)
  3632  		setFileBreakpoint(p, t, fixture.Source, 14)
  3633  
  3634  		assertNoError(p.Continue(), t, "Continue 1")
  3635  		if goversion.VersionAfterOrEqual(runtime.Version(), 1, 15) {
  3636  			testDeclLineCount(t, p, 8, []string{})
  3637  		} else {
  3638  			testDeclLineCount(t, p, 8, []string{"a"})
  3639  		}
  3640  
  3641  		assertNoError(p.Continue(), t, "Continue 2")
  3642  		testDeclLineCount(t, p, 9, []string{"a"})
  3643  
  3644  		assertNoError(p.Continue(), t, "Continue 3")
  3645  		if goversion.VersionAfterOrEqual(runtime.Version(), 1, 15) {
  3646  			testDeclLineCount(t, p, 10, []string{"a"})
  3647  		} else {
  3648  			testDeclLineCount(t, p, 10, []string{"a", "b"})
  3649  		}
  3650  
  3651  		assertNoError(p.Continue(), t, "Continue 4")
  3652  		testDeclLineCount(t, p, 11, []string{"a", "b"})
  3653  
  3654  		assertNoError(p.Continue(), t, "Continue 5")
  3655  		testDeclLineCount(t, p, 14, []string{"a", "b"})
  3656  	})
  3657  }
  3658  
  3659  func TestIssue1137(t *testing.T) {
  3660  	withTestProcess("dotpackagesiface", t, func(p *proc.Target, fixture protest.Fixture) {
  3661  		assertNoError(p.Continue(), t, "Continue()")
  3662  		v := evalVariable(p, t, "iface")
  3663  		assertNoError(v.Unreadable, t, "iface unreadable")
  3664  		v2 := evalVariable(p, t, "iface2")
  3665  		assertNoError(v2.Unreadable, t, "iface2 unreadable")
  3666  	})
  3667  }
  3668  
  3669  func TestIssue1101(t *testing.T) {
  3670  	// If a breakpoint is hit close to process death on a thread that isn't the
  3671  	// group leader the process could die while we are trying to stop it.
  3672  	//
  3673  	// This can be easily reproduced by having the goroutine that's executing
  3674  	// main.main (which will almost always run on the thread group leader) wait
  3675  	// for a second goroutine before exiting, then setting a breakpoint on the
  3676  	// second goroutine and stepping through it (see TestIssue1101 in
  3677  	// proc_test.go).
  3678  	//
  3679  	// When stepping over the return instruction of main.f the deferred
  3680  	// wg.Done() call will be executed which will cause the main goroutine to
  3681  	// resume and proceed to exit. Both the temporary breakpoint on wg.Done and
  3682  	// the temporary breakpoint on the return address of main.f will be in
  3683  	// close proximity to main.main calling os.Exit() and causing the death of
  3684  	// the thread group leader.
  3685  
  3686  	withTestProcess("issue1101", t, func(p *proc.Target, fixture protest.Fixture) {
  3687  		setFunctionBreakpoint(p, t, "main.f")
  3688  		assertNoError(p.Continue(), t, "Continue()")
  3689  		assertNoError(p.Next(), t, "Next() 1")
  3690  		assertNoError(p.Next(), t, "Next() 2")
  3691  		lastCmd := "Next() 3"
  3692  		exitErr := p.Next()
  3693  		if exitErr == nil {
  3694  			lastCmd = "final Continue()"
  3695  			exitErr = p.Continue()
  3696  		}
  3697  		if pexit, exited := exitErr.(proc.ErrProcessExited); exited {
  3698  			if pexit.Status != 2 && testBackend != "lldb" && (runtime.GOOS != "linux" || runtime.GOARCH != "386") {
  3699  				// Looks like there's a bug with debugserver on macOS that sometimes
  3700  				// will report exit status 0 instead of the proper exit status.
  3701  				//
  3702  				// Also it seems that sometimes on linux/386 we will not receive the
  3703  				// exit status. This happens if the process exits at the same time as it
  3704  				// receives a signal.
  3705  				t.Fatalf("process exited status %d (expected 2)", pexit.Status)
  3706  			}
  3707  		} else {
  3708  			assertNoError(exitErr, t, lastCmd)
  3709  			t.Fatalf("process did not exit after %s", lastCmd)
  3710  		}
  3711  	})
  3712  }
  3713  
  3714  func TestIssue1145(t *testing.T) {
  3715  	withTestProcess("sleep", t, func(p *proc.Target, fixture protest.Fixture) {
  3716  		setFileBreakpoint(p, t, fixture.Source, 18)
  3717  		assertNoError(p.Continue(), t, "Continue()")
  3718  		resumeChan := make(chan struct{}, 1)
  3719  		p.ResumeNotify(resumeChan)
  3720  		go func() {
  3721  			<-resumeChan
  3722  			time.Sleep(100 * time.Millisecond)
  3723  			p.RequestManualStop()
  3724  		}()
  3725  
  3726  		assertNoError(p.Next(), t, "Next()")
  3727  		if p.Breakpoints().HasSteppingBreakpoints() {
  3728  			t.Fatal("has internal breakpoints after manual stop request")
  3729  		}
  3730  	})
  3731  }
  3732  
  3733  func TestHaltKeepsSteppingBreakpoints(t *testing.T) {
  3734  	withTestProcess("sleep", t, func(p *proc.Target, fixture protest.Fixture) {
  3735  		p.KeepSteppingBreakpoints = proc.HaltKeepsSteppingBreakpoints
  3736  		setFileBreakpoint(p, t, fixture.Source, 18)
  3737  		assertNoError(p.Continue(), t, "Continue()")
  3738  		resumeChan := make(chan struct{}, 1)
  3739  		p.ResumeNotify(resumeChan)
  3740  		go func() {
  3741  			<-resumeChan
  3742  			time.Sleep(100 * time.Millisecond)
  3743  			p.RequestManualStop()
  3744  		}()
  3745  
  3746  		assertNoError(p.Next(), t, "Next()")
  3747  		if !p.Breakpoints().HasSteppingBreakpoints() {
  3748  			t.Fatal("does not have internal breakpoints after manual stop request")
  3749  		}
  3750  	})
  3751  }
  3752  
  3753  func TestDisassembleGlobalVars(t *testing.T) {
  3754  	skipOn(t, "broken - global variable symbolication", "arm64") // On ARM64 symLookup can't look up variables due to how they are loaded, see issue #1778
  3755  	// On 386 linux when pie, the genered code use __x86.get_pc_thunk to ensure position-independent.
  3756  	// Locate global variable by
  3757  	//    `CALL __x86.get_pc_thunk.ax(SB) 0xb0f7f
  3758  	//     LEAL 0xc0a19(AX), AX`
  3759  	// dynamically.
  3760  	if runtime.GOARCH == "386" && runtime.GOOS == "linux" && buildMode == "pie" {
  3761  		t.Skip("On 386 linux when pie, symLookup can't look up global variables")
  3762  	}
  3763  	withTestProcess("teststepconcurrent", t, func(p *proc.Target, fixture protest.Fixture) {
  3764  		mainfn := p.BinInfo().LookupFunc["main.main"]
  3765  		regs, _ := p.CurrentThread().Registers()
  3766  		text, err := proc.Disassemble(p.Memory(), regs, p.Breakpoints(), p.BinInfo(), mainfn.Entry, mainfn.End)
  3767  		assertNoError(err, t, "Disassemble")
  3768  		found := false
  3769  		for i := range text {
  3770  			if strings.Index(text[i].Text(proc.IntelFlavour, p.BinInfo()), "main.v") > 0 {
  3771  				found = true
  3772  				break
  3773  			}
  3774  		}
  3775  		if !found {
  3776  			t.Fatalf("could not find main.v reference in disassembly")
  3777  		}
  3778  	})
  3779  }
  3780  
  3781  func checkFrame(frame proc.Stackframe, fnname, file string, line int, inlined bool) error {
  3782  	if frame.Call.Fn == nil || frame.Call.Fn.Name != fnname {
  3783  		return fmt.Errorf("wrong function name: %s", fnname)
  3784  	}
  3785  	if file != "" {
  3786  		if frame.Call.File != file || frame.Call.Line != line {
  3787  			return fmt.Errorf("wrong file:line %s:%d", frame.Call.File, frame.Call.Line)
  3788  		}
  3789  	}
  3790  	if frame.Inlined != inlined {
  3791  		if inlined {
  3792  			return fmt.Errorf("not inlined")
  3793  		} else {
  3794  			return fmt.Errorf("inlined")
  3795  		}
  3796  	}
  3797  	return nil
  3798  }
  3799  
  3800  func TestAllPCsForFileLines(t *testing.T) {
  3801  	if ver, _ := goversion.Parse(runtime.Version()); ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}) {
  3802  		// Versions of go before 1.10 do not have DWARF information for inlined calls
  3803  		t.Skip("inlining not supported")
  3804  	}
  3805  	withTestProcessArgs("testinline", t, ".", []string{}, protest.EnableInlining, func(p *proc.Target, fixture protest.Fixture) {
  3806  		l2pcs := p.BinInfo().AllPCsForFileLines(fixture.Source, []int{7, 20})
  3807  		if len(l2pcs) != 2 {
  3808  			t.Fatalf("expected two map entries for %s:{%d,%d} (got %d: %v)", fixture.Source, 7, 20, len(l2pcs), l2pcs)
  3809  		}
  3810  		pcs := l2pcs[20]
  3811  		if len(pcs) < 1 {
  3812  			t.Fatalf("expected at least one location for %s:%d (got %d: %#x)", fixture.Source, 20, len(pcs), pcs)
  3813  		}
  3814  		pcs = l2pcs[7]
  3815  		if len(pcs) < 2 {
  3816  			t.Fatalf("expected at least two locations for %s:%d (got %d: %#x)", fixture.Source, 7, len(pcs), pcs)
  3817  		}
  3818  	})
  3819  }
  3820  
  3821  func TestInlinedStacktraceAndVariables(t *testing.T) {
  3822  	if ver, _ := goversion.Parse(runtime.Version()); ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}) {
  3823  		// Versions of go before 1.10 do not have DWARF information for inlined calls
  3824  		t.Skip("inlining not supported")
  3825  	}
  3826  
  3827  	firstCallCheck := &scopeCheck{
  3828  		line: 7,
  3829  		ok:   false,
  3830  		varChecks: []varCheck{
  3831  			varCheck{
  3832  				name:   "a",
  3833  				typ:    "int",
  3834  				kind:   reflect.Int,
  3835  				hasVal: true,
  3836  				intVal: 3,
  3837  			},
  3838  			varCheck{
  3839  				name:   "z",
  3840  				typ:    "int",
  3841  				kind:   reflect.Int,
  3842  				hasVal: true,
  3843  				intVal: 9,
  3844  			},
  3845  		},
  3846  	}
  3847  
  3848  	secondCallCheck := &scopeCheck{
  3849  		line: 7,
  3850  		ok:   false,
  3851  		varChecks: []varCheck{
  3852  			varCheck{
  3853  				name:   "a",
  3854  				typ:    "int",
  3855  				kind:   reflect.Int,
  3856  				hasVal: true,
  3857  				intVal: 4,
  3858  			},
  3859  			varCheck{
  3860  				name:   "z",
  3861  				typ:    "int",
  3862  				kind:   reflect.Int,
  3863  				hasVal: true,
  3864  				intVal: 16,
  3865  			},
  3866  		},
  3867  	}
  3868  
  3869  	withTestProcessArgs("testinline", t, ".", []string{}, protest.EnableInlining, func(p *proc.Target, fixture protest.Fixture) {
  3870  		pcs, err := proc.FindFileLocation(p, fixture.Source, 7)
  3871  		assertNoError(err, t, "LineToPC")
  3872  		if len(pcs) < 2 {
  3873  			t.Fatalf("expected at least two locations for %s:%d (got %d: %#x)", fixture.Source, 7, len(pcs), pcs)
  3874  		}
  3875  		for _, pc := range pcs {
  3876  			t.Logf("setting breakpoint at %#x\n", pc)
  3877  			_, err := p.SetBreakpoint(0, pc, proc.UserBreakpoint, nil)
  3878  			assertNoError(err, t, fmt.Sprintf("SetBreakpoint(%#x)", pc))
  3879  		}
  3880  
  3881  		// first inlined call
  3882  		assertNoError(p.Continue(), t, "Continue")
  3883  		frames, err := proc.ThreadStacktrace(p.CurrentThread(), 20)
  3884  		assertNoError(err, t, "ThreadStacktrace")
  3885  		t.Logf("Stacktrace:\n")
  3886  		for i := range frames {
  3887  			t.Logf("\t%s at %s:%d (%#x)\n", frames[i].Call.Fn.Name, frames[i].Call.File, frames[i].Call.Line, frames[i].Current.PC)
  3888  		}
  3889  
  3890  		if err := checkFrame(frames[0], "main.inlineThis", fixture.Source, 7, true); err != nil {
  3891  			t.Fatalf("Wrong frame 0: %v", err)
  3892  		}
  3893  		if err := checkFrame(frames[1], "main.main", fixture.Source, 18, false); err != nil {
  3894  			t.Fatalf("Wrong frame 1: %v", err)
  3895  		}
  3896  
  3897  		if avar, _ := constant.Int64Val(evalVariable(p, t, "a").Value); avar != 3 {
  3898  			t.Fatalf("value of 'a' variable is not 3 (%d)", avar)
  3899  		}
  3900  		if zvar, _ := constant.Int64Val(evalVariable(p, t, "z").Value); zvar != 9 {
  3901  			t.Fatalf("value of 'z' variable is not 9 (%d)", zvar)
  3902  		}
  3903  
  3904  		if _, ok := firstCallCheck.checkLocalsAndArgs(p, t); !ok {
  3905  			t.Fatalf("exiting for past errors")
  3906  		}
  3907  
  3908  		// second inlined call
  3909  		assertNoError(p.Continue(), t, "Continue")
  3910  		frames, err = proc.ThreadStacktrace(p.CurrentThread(), 20)
  3911  		assertNoError(err, t, "ThreadStacktrace (2)")
  3912  		t.Logf("Stacktrace 2:\n")
  3913  		for i := range frames {
  3914  			t.Logf("\t%s at %s:%d (%#x)\n", frames[i].Call.Fn.Name, frames[i].Call.File, frames[i].Call.Line, frames[i].Current.PC)
  3915  		}
  3916  
  3917  		if err := checkFrame(frames[0], "main.inlineThis", fixture.Source, 7, true); err != nil {
  3918  			t.Fatalf("Wrong frame 0: %v", err)
  3919  		}
  3920  		if err := checkFrame(frames[1], "main.main", fixture.Source, 19, false); err != nil {
  3921  			t.Fatalf("Wrong frame 1: %v", err)
  3922  		}
  3923  
  3924  		if avar, _ := constant.Int64Val(evalVariable(p, t, "a").Value); avar != 4 {
  3925  			t.Fatalf("value of 'a' variable is not 3 (%d)", avar)
  3926  		}
  3927  		if zvar, _ := constant.Int64Val(evalVariable(p, t, "z").Value); zvar != 16 {
  3928  			t.Fatalf("value of 'z' variable is not 9 (%d)", zvar)
  3929  		}
  3930  		if bvar, err := evalVariableOrError(p, "b"); err == nil {
  3931  			t.Fatalf("expected error evaluating 'b', but it succeeded instead: %v", bvar)
  3932  		}
  3933  
  3934  		if _, ok := secondCallCheck.checkLocalsAndArgs(p, t); !ok {
  3935  			t.Fatalf("exiting for past errors")
  3936  		}
  3937  	})
  3938  }
  3939  
  3940  func TestInlineStep(t *testing.T) {
  3941  	if ver, _ := goversion.Parse(runtime.Version()); ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}) {
  3942  		// Versions of go before 1.10 do not have DWARF information for inlined calls
  3943  		t.Skip("inlining not supported")
  3944  	}
  3945  	testseq2Args(".", []string{}, protest.EnableInlining, t, "testinline", "", []seqTest{
  3946  		{contContinue, 18},
  3947  		{contStep, 6},
  3948  		{contStep, 7},
  3949  		{contStep, 18},
  3950  		{contStep, 19},
  3951  	})
  3952  }
  3953  
  3954  func TestInlineNext(t *testing.T) {
  3955  	if ver, _ := goversion.Parse(runtime.Version()); ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}) {
  3956  		// Versions of go before 1.10 do not have DWARF information for inlined calls
  3957  		t.Skip("inlining not supported")
  3958  	}
  3959  	testseq2Args(".", []string{}, protest.EnableInlining, t, "testinline", "", []seqTest{
  3960  		{contContinue, 18},
  3961  		{contStep, 6},
  3962  		{contNext, 7},
  3963  		{contNext, 18},
  3964  		{contNext, 19},
  3965  	})
  3966  }
  3967  
  3968  func TestInlineStepOver(t *testing.T) {
  3969  	if ver, _ := goversion.Parse(runtime.Version()); ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}) {
  3970  		// Versions of go before 1.10 do not have DWARF information for inlined calls
  3971  		t.Skip("inlining not supported")
  3972  	}
  3973  	testseq2Args(".", []string{}, protest.EnableInlining, t, "testinline", "", []seqTest{
  3974  		{contContinue, 18},
  3975  		{contNext, 19},
  3976  		{contNext, 20},
  3977  	})
  3978  }
  3979  
  3980  func TestInlineStepOut(t *testing.T) {
  3981  	if ver, _ := goversion.Parse(runtime.Version()); ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}) {
  3982  		// Versions of go before 1.10 do not have DWARF information for inlined calls
  3983  		t.Skip("inlining not supported")
  3984  	}
  3985  	testseq2Args(".", []string{}, protest.EnableInlining, t, "testinline", "", []seqTest{
  3986  		{contContinue, 18},
  3987  		{contStep, 6},
  3988  		{contStepout, 18},
  3989  	})
  3990  }
  3991  
  3992  func TestInlineFunctionList(t *testing.T) {
  3993  	// We should be able to list all functions, even inlined ones.
  3994  	if ver, _ := goversion.Parse(runtime.Version()); ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}) {
  3995  		// Versions of go before 1.10 do not have DWARF information for inlined calls
  3996  		t.Skip("inlining not supported")
  3997  	}
  3998  	withTestProcessArgs("testinline", t, ".", []string{}, protest.EnableInlining|protest.EnableOptimization, func(p *proc.Target, fixture protest.Fixture) {
  3999  		var found bool
  4000  		for _, fn := range p.BinInfo().Functions {
  4001  			if strings.Contains(fn.Name, "inlineThis") {
  4002  				found = true
  4003  				break
  4004  			}
  4005  		}
  4006  		if !found {
  4007  			t.Fatal("inline function not returned")
  4008  		}
  4009  	})
  4010  }
  4011  
  4012  func TestInlineBreakpoint(t *testing.T) {
  4013  	// We should be able to set a breakpoint on the call site of an inlined function.
  4014  	if ver, _ := goversion.Parse(runtime.Version()); ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}) {
  4015  		// Versions of go before 1.10 do not have DWARF information for inlined calls
  4016  		t.Skip("inlining not supported")
  4017  	}
  4018  	withTestProcessArgs("testinline", t, ".", []string{}, protest.EnableInlining|protest.EnableOptimization, func(p *proc.Target, fixture protest.Fixture) {
  4019  		pcs, err := proc.FindFileLocation(p, fixture.Source, 17)
  4020  		if err != nil {
  4021  			t.Fatal(err)
  4022  		}
  4023  		t.Logf("%#v\n", pcs)
  4024  		if len(pcs) != 1 {
  4025  			t.Fatalf("unable to get PC for inlined function call: %v", pcs)
  4026  		}
  4027  		fn := p.BinInfo().PCToFunc(pcs[0])
  4028  		expectedFn := "main.main"
  4029  		if fn.Name != expectedFn {
  4030  			t.Fatalf("incorrect function returned, expected %s, got %s", expectedFn, fn.Name)
  4031  		}
  4032  		_, err = p.SetBreakpoint(0, pcs[0], proc.UserBreakpoint, nil)
  4033  		if err != nil {
  4034  			t.Fatalf("unable to set breakpoint: %v", err)
  4035  		}
  4036  	})
  4037  }
  4038  
  4039  func TestDoubleInlineBreakpoint(t *testing.T) {
  4040  	// We should be able to set a breakpoint on an inlined function that
  4041  	// has been inlined within an inlined function.
  4042  	if ver, _ := goversion.Parse(runtime.Version()); ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}) {
  4043  		// Versions of go before 1.10 do not have DWARF information for inlined calls
  4044  		t.Skip("inlining not supported")
  4045  	}
  4046  	withTestProcessArgs("doubleinline", t, ".", []string{}, protest.EnableInlining|protest.EnableOptimization, func(p *proc.Target, fixture protest.Fixture) {
  4047  		fns, err := p.BinInfo().FindFunction("main.(*Rectangle).Height")
  4048  		if err != nil {
  4049  			t.Fatal(err)
  4050  		}
  4051  		if len(fns) != 1 {
  4052  			t.Fatalf("expected one function for Height, got %d", len(fns))
  4053  		}
  4054  		if len(fns[0].InlinedCalls) != 1 {
  4055  			t.Fatalf("expected one inlined call for Height, got %d", len(fns[0].InlinedCalls))
  4056  		}
  4057  	})
  4058  }
  4059  
  4060  func TestIssue951(t *testing.T) {
  4061  	if ver, _ := goversion.Parse(runtime.Version()); ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 9, Rev: -1}) {
  4062  		t.Skip("scopes not implemented in <=go1.8")
  4063  	}
  4064  
  4065  	withTestProcess("issue951", t, func(p *proc.Target, fixture protest.Fixture) {
  4066  		assertNoError(p.Continue(), t, "Continue()")
  4067  		scope, err := proc.GoroutineScope(p, p.CurrentThread())
  4068  		assertNoError(err, t, "GoroutineScope")
  4069  		args, err := scope.FunctionArguments(normalLoadConfig)
  4070  		assertNoError(err, t, "FunctionArguments")
  4071  		t.Logf("%#v", args[0])
  4072  		if args[0].Flags&proc.VariableShadowed == 0 {
  4073  			t.Error("argument is not shadowed")
  4074  		}
  4075  		vars, err := scope.LocalVariables(normalLoadConfig)
  4076  		assertNoError(err, t, "LocalVariables")
  4077  		shadowed, notShadowed := 0, 0
  4078  		for i := range vars {
  4079  			t.Logf("var %d: %#v\n", i, vars[i])
  4080  			if vars[i].Flags&proc.VariableShadowed != 0 {
  4081  				shadowed++
  4082  			} else {
  4083  				notShadowed++
  4084  			}
  4085  		}
  4086  		if shadowed != 1 || notShadowed != 1 {
  4087  			t.Errorf("Wrong number of shadowed/non-shadowed local variables: %d %d", shadowed, notShadowed)
  4088  		}
  4089  	})
  4090  }
  4091  
  4092  func TestDWZCompression(t *testing.T) {
  4093  	// If dwz is not available in the system, skip this test
  4094  	if _, err := exec.LookPath("dwz"); err != nil {
  4095  		t.Skip("dwz not installed")
  4096  	}
  4097  
  4098  	withTestProcessArgs("dwzcompression", t, ".", []string{}, protest.EnableDWZCompression, func(p *proc.Target, fixture protest.Fixture) {
  4099  		setFunctionBreakpoint(p, t, "C.fortytwo")
  4100  		assertNoError(p.Continue(), t, "first Continue()")
  4101  		val := evalVariable(p, t, "stdin")
  4102  		if val.RealType == nil {
  4103  			t.Errorf("Can't find type for \"stdin\" global variable")
  4104  		}
  4105  	})
  4106  }
  4107  
  4108  func TestMapLoadConfigWithReslice(t *testing.T) {
  4109  	// Check that load configuration is respected for resliced maps.
  4110  	withTestProcess("testvariables2", t, func(p *proc.Target, fixture protest.Fixture) {
  4111  		zolotovLoadCfg := proc.LoadConfig{FollowPointers: true, MaxStructFields: -1, MaxVariableRecurse: 3, MaxStringLen: 10, MaxArrayValues: 10}
  4112  		assertNoError(p.Continue(), t, "First Continue()")
  4113  		scope, err := proc.GoroutineScope(p, p.CurrentThread())
  4114  		assertNoError(err, t, "GoroutineScope")
  4115  		m1, err := scope.EvalExpression("m1", zolotovLoadCfg)
  4116  		assertNoError(err, t, "EvalVariable")
  4117  		t.Logf("m1 returned children %d (%d)", len(m1.Children)/2, m1.Len)
  4118  
  4119  		expr := fmt.Sprintf("(*(*%q)(%d))[10:]", m1.DwarfType.String(), m1.Addr)
  4120  		t.Logf("expr %q\n", expr)
  4121  
  4122  		m1cont, err := scope.EvalExpression(expr, zolotovLoadCfg)
  4123  		assertNoError(err, t, "EvalVariable")
  4124  
  4125  		t.Logf("m1cont returned children %d", len(m1cont.Children)/2)
  4126  
  4127  		if len(m1cont.Children) != 20 {
  4128  			t.Fatalf("wrong number of children returned %d\n", len(m1cont.Children)/2)
  4129  		}
  4130  	})
  4131  }
  4132  
  4133  func TestStepOutReturn(t *testing.T) {
  4134  	ver, _ := goversion.Parse(runtime.Version())
  4135  	if ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}) {
  4136  		t.Skip("return variables aren't marked on 1.9 or earlier")
  4137  	}
  4138  	withTestProcess("stepoutret", t, func(p *proc.Target, fixture protest.Fixture) {
  4139  		setFunctionBreakpoint(p, t, "main.stepout")
  4140  		assertNoError(p.Continue(), t, "Continue")
  4141  		assertNoError(p.StepOut(), t, "StepOut")
  4142  		ret := p.CurrentThread().Common().ReturnValues(normalLoadConfig)
  4143  		if len(ret) != 2 {
  4144  			t.Fatalf("wrong number of return values %v", ret)
  4145  		}
  4146  
  4147  		stridx := 0
  4148  		numidx := 1
  4149  
  4150  		if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 12) {
  4151  			// in 1.11 and earlier the order of return values in DWARF is
  4152  			// unspecified, in 1.11 and later it follows the order of definition
  4153  			// specified by the user
  4154  			for i := range ret {
  4155  				if ret[i].Name == "str" {
  4156  					stridx = i
  4157  					numidx = 1 - i
  4158  					break
  4159  				}
  4160  			}
  4161  		}
  4162  
  4163  		if ret[stridx].Name != "str" {
  4164  			t.Fatalf("(str) bad return value name %s", ret[stridx].Name)
  4165  		}
  4166  		if ret[stridx].Kind != reflect.String {
  4167  			t.Fatalf("(str) bad return value kind %v", ret[stridx].Kind)
  4168  		}
  4169  		if s := constant.StringVal(ret[stridx].Value); s != "return 47" {
  4170  			t.Fatalf("(str) bad return value %q", s)
  4171  		}
  4172  
  4173  		if ret[numidx].Name != "num" {
  4174  			t.Fatalf("(num) bad return value name %s", ret[numidx].Name)
  4175  		}
  4176  		if ret[numidx].Kind != reflect.Int {
  4177  			t.Fatalf("(num) bad return value kind %v", ret[numidx].Kind)
  4178  		}
  4179  		if n, _ := constant.Int64Val(ret[numidx].Value); n != 48 {
  4180  			t.Fatalf("(num) bad return value %d", n)
  4181  		}
  4182  	})
  4183  }
  4184  
  4185  func TestOptimizationCheck(t *testing.T) {
  4186  	withTestProcess("continuetestprog", t, func(p *proc.Target, fixture protest.Fixture) {
  4187  		fn := p.BinInfo().LookupFunc["main.main"]
  4188  		if fn.Optimized() {
  4189  			t.Fatalf("main.main is optimized")
  4190  		}
  4191  	})
  4192  
  4193  	if goversion.VersionAfterOrEqual(runtime.Version(), 1, 10) {
  4194  		withTestProcessArgs("continuetestprog", t, ".", []string{}, protest.EnableOptimization|protest.EnableInlining, func(p *proc.Target, fixture protest.Fixture) {
  4195  			fn := p.BinInfo().LookupFunc["main.main"]
  4196  			if !fn.Optimized() {
  4197  				t.Fatalf("main.main is not optimized")
  4198  			}
  4199  		})
  4200  	}
  4201  }
  4202  
  4203  func TestIssue1264(t *testing.T) {
  4204  	// It should be possible to set a breakpoint condition that consists only
  4205  	// of evaluating a single boolean variable.
  4206  	withTestProcess("issue1264", t, func(p *proc.Target, fixture protest.Fixture) {
  4207  		bp := setFileBreakpoint(p, t, fixture.Source, 8)
  4208  		bp.UserBreaklet().Cond = &ast.Ident{Name: "equalsTwo"}
  4209  		assertNoError(p.Continue(), t, "Continue()")
  4210  		assertLineNumber(p, t, 8, "after continue")
  4211  	})
  4212  }
  4213  
  4214  func TestReadDefer(t *testing.T) {
  4215  	withTestProcess("deferstack", t, func(p *proc.Target, fixture protest.Fixture) {
  4216  		assertNoError(p.Continue(), t, "Continue")
  4217  		frames, err := p.SelectedGoroutine().Stacktrace(10, proc.StacktraceReadDefers)
  4218  		assertNoError(err, t, "Stacktrace")
  4219  
  4220  		logStacktrace(t, p, frames)
  4221  
  4222  		examples := []struct {
  4223  			frameIdx     int
  4224  			topmostDefer string
  4225  			defers       []string
  4226  		}{
  4227  			// main.call3 (defers nothing, topmost defer main.f2)
  4228  			{0, "main.f2", []string{}},
  4229  
  4230  			// main.call2 (defers main.f2, main.f3, topmost defer main.f2)
  4231  			{1, "main.f2", []string{"main.f2", "main.f3"}},
  4232  
  4233  			// main.call1 (defers main.f1, main.f2, topmost defer main.f1)
  4234  			{2, "main.f1", []string{"main.f1", "main.f2"}},
  4235  
  4236  			// main.main (defers nothing)
  4237  			{3, "", []string{}}}
  4238  
  4239  		defercheck := func(d *proc.Defer, deferName, tgt string, frameIdx int) {
  4240  			if d == nil {
  4241  				t.Fatalf("expected %q as %s of frame %d, got nothing", tgt, deferName, frameIdx)
  4242  			}
  4243  			if d.Unreadable != nil {
  4244  				t.Fatalf("expected %q as %s of frame %d, got unreadable defer: %v", tgt, deferName, frameIdx, d.Unreadable)
  4245  			}
  4246  			_, _, dfn := d.DeferredFunc(p)
  4247  			if dfn == nil {
  4248  				t.Fatalf("expected %q as %s of frame %d, got %#x", tgt, deferName, frameIdx, d.DwrapPC)
  4249  			}
  4250  			if dfn.Name != tgt {
  4251  				t.Fatalf("expected %q as %s of frame %d, got %q", tgt, deferName, frameIdx, dfn.Name)
  4252  			}
  4253  		}
  4254  
  4255  		for _, example := range examples {
  4256  			frame := &frames[example.frameIdx]
  4257  
  4258  			if example.topmostDefer != "" {
  4259  				defercheck(frame.TopmostDefer, "topmost defer", example.topmostDefer, example.frameIdx)
  4260  			}
  4261  
  4262  			if len(example.defers) != len(frames[example.frameIdx].Defers) {
  4263  				t.Fatalf("expected %d defers for %d, got %v", len(example.defers), example.frameIdx, frame.Defers)
  4264  			}
  4265  
  4266  			for deferIdx := range example.defers {
  4267  				defercheck(frame.Defers[deferIdx], fmt.Sprintf("defer %d", deferIdx), example.defers[deferIdx], example.frameIdx)
  4268  			}
  4269  		}
  4270  	})
  4271  }
  4272  
  4273  func TestNextUnknownInstr(t *testing.T) {
  4274  	skipUnlessOn(t, "amd64 only", "amd64")
  4275  	if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 10) {
  4276  		t.Skip("versions of Go before 1.10 can't assemble the instruction VPUNPCKLWD")
  4277  	}
  4278  	withTestProcess("nodisasm/", t, func(p *proc.Target, fixture protest.Fixture) {
  4279  		setFunctionBreakpoint(p, t, "main.asmFunc")
  4280  		assertNoError(p.Continue(), t, "Continue()")
  4281  		assertNoError(p.Next(), t, "Next()")
  4282  	})
  4283  }
  4284  
  4285  func TestReadDeferArgs(t *testing.T) {
  4286  	if goversion.VersionAfterOrEqual(runtime.Version(), 1, 17) {
  4287  		// When regabi is enabled in Go 1.17 and later, reading arguments of
  4288  		// deferred functions becomes significantly more complicated because of
  4289  		// the autogenerated code used to unpack the argument frame stored in
  4290  		// runtime._defer into registers.
  4291  		// We either need to know how to do the translation, implementing the ABI1
  4292  		// rules in Delve, or have some assistance from the compiler (for example
  4293  		// have the dwrap function contain entries for each of the captured
  4294  		// variables with a location describing their offset from DX).
  4295  		// Ultimately this feature is unimportant enough that we can leave it
  4296  		// disabled for now.
  4297  		t.Skip("unsupported")
  4298  	}
  4299  	var tests = []struct {
  4300  		frame, deferCall int
  4301  		a, b             int64
  4302  	}{
  4303  		{1, 1, 42, 61},
  4304  		{2, 2, 1, -1},
  4305  	}
  4306  
  4307  	withTestProcess("deferstack", t, func(p *proc.Target, fixture protest.Fixture) {
  4308  		assertNoError(p.Continue(), t, "Continue()")
  4309  
  4310  		for _, test := range tests {
  4311  			scope, err := proc.ConvertEvalScope(p, -1, test.frame, test.deferCall)
  4312  			assertNoError(err, t, fmt.Sprintf("ConvertEvalScope(-1, %d, %d)", test.frame, test.deferCall))
  4313  
  4314  			if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 17) {
  4315  				// In Go 1.17 deferred function calls can end up inside a wrapper, and
  4316  				// the scope for this evaluation needs to be the wrapper.
  4317  				if scope.Fn.Name != "main.f2" {
  4318  					t.Fatalf("expected function \"main.f2\" got %q", scope.Fn.Name)
  4319  				}
  4320  			}
  4321  
  4322  			avar, err := scope.EvalExpression("a", normalLoadConfig)
  4323  			if err != nil {
  4324  				t.Fatal(err)
  4325  			}
  4326  			bvar, err := scope.EvalExpression("b", normalLoadConfig)
  4327  			if err != nil {
  4328  				t.Fatal(err)
  4329  			}
  4330  
  4331  			a, _ := constant.Int64Val(avar.Value)
  4332  			b, _ := constant.Int64Val(bvar.Value)
  4333  
  4334  			if a != test.a {
  4335  				t.Errorf("value of argument 'a' at frame %d, deferred call %d: %d (expected %d)", test.frame, test.deferCall, a, test.a)
  4336  			}
  4337  
  4338  			if b != test.b {
  4339  				t.Errorf("value of argument 'b' at frame %d, deferred call %d: %d (expected %d)", test.frame, test.deferCall, b, test.b)
  4340  			}
  4341  		}
  4342  	})
  4343  }
  4344  
  4345  func TestIssue1374(t *testing.T) {
  4346  	// Continue did not work when stopped at a breakpoint immediately after calling CallFunction.
  4347  	protest.MustSupportFunctionCalls(t, testBackend)
  4348  	withTestProcess("issue1374", t, func(p *proc.Target, fixture protest.Fixture) {
  4349  		setFileBreakpoint(p, t, fixture.Source, 7)
  4350  		assertNoError(p.Continue(), t, "First Continue")
  4351  		assertLineNumber(p, t, 7, "Did not continue to correct location (first continue),")
  4352  		assertNoError(proc.EvalExpressionWithCalls(p, p.SelectedGoroutine(), "getNum()", normalLoadConfig, true), t, "Call")
  4353  		err := p.Continue()
  4354  		if _, isexited := err.(proc.ErrProcessExited); !isexited {
  4355  			regs, _ := p.CurrentThread().Registers()
  4356  			f, l, _ := p.BinInfo().PCToLine(regs.PC())
  4357  			t.Fatalf("expected process exited error got %v at %s:%d", err, f, l)
  4358  		}
  4359  	})
  4360  }
  4361  
  4362  func TestIssue1432(t *testing.T) {
  4363  	// Check that taking the address of a struct, casting it into a pointer to
  4364  	// the struct's type and then accessing a member field will still:
  4365  	// - perform auto-dereferencing on struct member access
  4366  	// - yield a Variable that's ultimately assignable (i.e. has an address)
  4367  	withTestProcess("issue1432", t, func(p *proc.Target, fixture protest.Fixture) {
  4368  		assertNoError(p.Continue(), t, "Continue")
  4369  		svar := evalVariable(p, t, "s")
  4370  		t.Logf("%#x", svar.Addr)
  4371  
  4372  		scope, err := proc.GoroutineScope(p, p.CurrentThread())
  4373  		assertNoError(err, t, "GoroutineScope()")
  4374  
  4375  		err = scope.SetVariable(fmt.Sprintf("(*\"main.s\")(%#x).i", svar.Addr), "10")
  4376  		assertNoError(err, t, "SetVariable")
  4377  	})
  4378  }
  4379  
  4380  func TestGoroutinesInfoLimit(t *testing.T) {
  4381  	withTestProcess("teststepconcurrent", t, func(p *proc.Target, fixture protest.Fixture) {
  4382  		setFileBreakpoint(p, t, fixture.Source, 37)
  4383  		assertNoError(p.Continue(), t, "Continue()")
  4384  
  4385  		gcount := 0
  4386  		nextg := 0
  4387  		const goroutinesInfoLimit = 10
  4388  		for nextg >= 0 {
  4389  			oldnextg := nextg
  4390  			var gs []*proc.G
  4391  			var err error
  4392  			gs, nextg, err = proc.GoroutinesInfo(p, nextg, goroutinesInfoLimit)
  4393  			assertNoError(err, t, fmt.Sprintf("GoroutinesInfo(%d, %d)", oldnextg, goroutinesInfoLimit))
  4394  			gcount += len(gs)
  4395  			t.Logf("got %d goroutines\n", len(gs))
  4396  		}
  4397  
  4398  		t.Logf("number of goroutines: %d\n", gcount)
  4399  
  4400  		gs, _, err := proc.GoroutinesInfo(p, 0, 0)
  4401  		assertNoError(err, t, "GoroutinesInfo(0, 0)")
  4402  		t.Logf("number of goroutines (full scan): %d\n", gcount)
  4403  		if len(gs) != gcount {
  4404  			t.Fatalf("mismatch in the number of goroutines %d %d\n", gcount, len(gs))
  4405  		}
  4406  	})
  4407  }
  4408  
  4409  func TestIssue1469(t *testing.T) {
  4410  	withTestProcess("issue1469", t, func(p *proc.Target, fixture protest.Fixture) {
  4411  		setFileBreakpoint(p, t, fixture.Source, 13)
  4412  		assertNoError(p.Continue(), t, "Continue()")
  4413  
  4414  		gid2thread := make(map[int][]proc.Thread)
  4415  		for _, thread := range p.ThreadList() {
  4416  			g, _ := proc.GetG(thread)
  4417  			if g == nil {
  4418  				continue
  4419  			}
  4420  			gid2thread[g.ID] = append(gid2thread[g.ID], thread)
  4421  		}
  4422  
  4423  		for gid := range gid2thread {
  4424  			if len(gid2thread[gid]) > 1 {
  4425  				t.Logf("too many threads running goroutine %d", gid)
  4426  				for _, thread := range gid2thread[gid] {
  4427  					t.Logf("\tThread %d", thread.ThreadID())
  4428  					frames, err := proc.ThreadStacktrace(thread, 20)
  4429  					if err != nil {
  4430  						t.Logf("\t\tcould not get stacktrace %v", err)
  4431  					}
  4432  					for _, frame := range frames {
  4433  						t.Logf("\t\t%#x at %s:%d (systemstack: %v)", frame.Call.PC, frame.Call.File, frame.Call.Line, frame.SystemStack)
  4434  					}
  4435  				}
  4436  			}
  4437  		}
  4438  	})
  4439  }
  4440  
  4441  func TestDeadlockBreakpoint(t *testing.T) {
  4442  	skipOn(t, "upstream issue - https://github.com/golang/go/issues/29322", "pie")
  4443  	deadlockBp := proc.FatalThrow
  4444  	if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 11) {
  4445  		deadlockBp = proc.UnrecoveredPanic
  4446  	}
  4447  	withTestProcess("testdeadlock", t, func(p *proc.Target, fixture protest.Fixture) {
  4448  		assertNoError(p.Continue(), t, "Continue()")
  4449  
  4450  		bp := p.CurrentThread().Breakpoint()
  4451  		if bp.Breakpoint == nil || bp.Logical.Name != deadlockBp {
  4452  			t.Fatalf("did not stop at deadlock breakpoint %v", bp)
  4453  		}
  4454  	})
  4455  }
  4456  
  4457  func findSource(source string, sources []string) bool {
  4458  	for _, s := range sources {
  4459  		if s == source {
  4460  			return true
  4461  		}
  4462  	}
  4463  	return false
  4464  }
  4465  
  4466  func TestListImages(t *testing.T) {
  4467  	pluginFixtures := protest.WithPlugins(t, protest.AllNonOptimized, "plugin1/", "plugin2/")
  4468  
  4469  	withTestProcessArgs("plugintest", t, ".", []string{pluginFixtures[0].Path, pluginFixtures[1].Path}, protest.AllNonOptimized, func(p *proc.Target, fixture protest.Fixture) {
  4470  		if !findSource(fixture.Source, p.BinInfo().Sources) {
  4471  			t.Fatalf("could not find %s in sources: %q\n", fixture.Source, p.BinInfo().Sources)
  4472  		}
  4473  
  4474  		assertNoError(p.Continue(), t, "first continue")
  4475  		f, l := currentLineNumber(p, t)
  4476  		plugin1Found := false
  4477  		t.Logf("Libraries before %s:%d:", f, l)
  4478  		for _, image := range p.BinInfo().Images {
  4479  			t.Logf("\t%#x %q err:%v", image.StaticBase, image.Path, image.LoadError())
  4480  			if image.Path == pluginFixtures[0].Path {
  4481  				plugin1Found = true
  4482  			}
  4483  		}
  4484  		if !plugin1Found {
  4485  			t.Fatalf("Could not find plugin1")
  4486  		}
  4487  		if !findSource(fixture.Source, p.BinInfo().Sources) {
  4488  			// Source files for the base program must be available even after a plugin is loaded. Issue #2074.
  4489  			t.Fatalf("could not find %s in sources (after loading plugin): %q\n", fixture.Source, p.BinInfo().Sources)
  4490  		}
  4491  		assertNoError(p.Continue(), t, "second continue")
  4492  		f, l = currentLineNumber(p, t)
  4493  		plugin1Found, plugin2Found := false, false
  4494  		t.Logf("Libraries after %s:%d:", f, l)
  4495  		for _, image := range p.BinInfo().Images {
  4496  			t.Logf("\t%#x %q err:%v", image.StaticBase, image.Path, image.LoadError())
  4497  			switch image.Path {
  4498  			case pluginFixtures[0].Path:
  4499  				plugin1Found = true
  4500  			case pluginFixtures[1].Path:
  4501  				plugin2Found = true
  4502  			}
  4503  		}
  4504  		if !plugin1Found {
  4505  			t.Fatalf("Could not find plugin1")
  4506  		}
  4507  		if !plugin2Found {
  4508  			t.Fatalf("Could not find plugin2")
  4509  		}
  4510  	})
  4511  }
  4512  
  4513  func TestAncestors(t *testing.T) {
  4514  	if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 11) {
  4515  		t.Skip("not supported on Go <= 1.10")
  4516  	}
  4517  	savedGodebug := os.Getenv("GODEBUG")
  4518  	os.Setenv("GODEBUG", "tracebackancestors=100")
  4519  	defer os.Setenv("GODEBUG", savedGodebug)
  4520  	withTestProcess("testnextprog", t, func(p *proc.Target, fixture protest.Fixture) {
  4521  		setFunctionBreakpoint(p, t, "main.testgoroutine")
  4522  		assertNoError(p.Continue(), t, "Continue()")
  4523  		as, err := proc.Ancestors(p, p.SelectedGoroutine(), 1000)
  4524  		assertNoError(err, t, "Ancestors")
  4525  		t.Logf("ancestors: %#v\n", as)
  4526  		if len(as) != 1 {
  4527  			t.Fatalf("expected only one ancestor got %d", len(as))
  4528  		}
  4529  		mainFound := false
  4530  		for i, a := range as {
  4531  			astack, err := a.Stack(100)
  4532  			assertNoError(err, t, fmt.Sprintf("Ancestor %d stack", i))
  4533  			t.Logf("ancestor %d\n", i)
  4534  			logStacktrace(t, p, astack)
  4535  			for _, frame := range astack {
  4536  				if frame.Current.Fn != nil && frame.Current.Fn.Name == "main.main" {
  4537  					mainFound = true
  4538  				}
  4539  			}
  4540  		}
  4541  		if !mainFound {
  4542  			t.Fatal("could not find main.main function in ancestors")
  4543  		}
  4544  	})
  4545  }
  4546  
  4547  func testCallConcurrentCheckReturns(p *proc.Target, t *testing.T, gid1, gid2 int) int {
  4548  	found := 0
  4549  	for _, thread := range p.ThreadList() {
  4550  		g, _ := proc.GetG(thread)
  4551  		if g == nil || (g.ID != gid1 && g.ID != gid2) {
  4552  			continue
  4553  		}
  4554  		retvals := thread.Common().ReturnValues(normalLoadConfig)
  4555  		if len(retvals) == 0 {
  4556  			continue
  4557  		}
  4558  		n, _ := constant.Int64Val(retvals[0].Value)
  4559  		t.Logf("injection on goroutine %d (thread %d) returned %v\n", g.ID, thread.ThreadID(), n)
  4560  		switch g.ID {
  4561  		case gid1:
  4562  			if n != 11 {
  4563  				t.Errorf("wrong return value for goroutine %d", g.ID)
  4564  			}
  4565  			found++
  4566  		case gid2:
  4567  			if n != 12 {
  4568  				t.Errorf("wrong return value for goroutine %d", g.ID)
  4569  			}
  4570  			found++
  4571  		}
  4572  	}
  4573  	return found
  4574  }
  4575  
  4576  func TestCallConcurrent(t *testing.T) {
  4577  	skipOn(t, "broken", "freebsd")
  4578  	protest.MustSupportFunctionCalls(t, testBackend)
  4579  	withTestProcess("teststepconcurrent", t, func(p *proc.Target, fixture protest.Fixture) {
  4580  		bp := setFileBreakpoint(p, t, fixture.Source, 24)
  4581  		assertNoError(p.Continue(), t, "Continue()")
  4582  		//_, err := p.ClearBreakpoint(bp.Addr)
  4583  		//assertNoError(err, t, "ClearBreakpoint() returned an error")
  4584  
  4585  		gid1 := p.SelectedGoroutine().ID
  4586  		t.Logf("starting injection in %d / %d", p.SelectedGoroutine().ID, p.CurrentThread().ThreadID())
  4587  		assertNoError(proc.EvalExpressionWithCalls(p, p.SelectedGoroutine(), "Foo(10, 1)", normalLoadConfig, false), t, "EvalExpressionWithCalls()")
  4588  
  4589  		returned := testCallConcurrentCheckReturns(p, t, gid1, -1)
  4590  
  4591  		curthread := p.CurrentThread()
  4592  		if curbp := curthread.Breakpoint(); curbp.Breakpoint == nil || curbp.LogicalID() != bp.LogicalID() || returned > 0 {
  4593  			t.Logf("skipping test, the call injection terminated before we hit a breakpoint in a different thread")
  4594  			return
  4595  		}
  4596  
  4597  		err := p.ClearBreakpoint(bp.Addr)
  4598  		assertNoError(err, t, "ClearBreakpoint() returned an error")
  4599  
  4600  		gid2 := p.SelectedGoroutine().ID
  4601  		t.Logf("starting second injection in %d / %d", p.SelectedGoroutine().ID, p.CurrentThread().ThreadID())
  4602  		assertNoError(proc.EvalExpressionWithCalls(p, p.SelectedGoroutine(), "Foo(10, 2)", normalLoadConfig, false), t, "EvalExpressioniWithCalls")
  4603  
  4604  		for {
  4605  			returned += testCallConcurrentCheckReturns(p, t, gid1, gid2)
  4606  			if returned >= 2 {
  4607  				break
  4608  			}
  4609  			t.Logf("Continuing... %d", returned)
  4610  			assertNoError(p.Continue(), t, "Continue()")
  4611  		}
  4612  
  4613  		p.Continue()
  4614  	})
  4615  }
  4616  
  4617  func TestPluginStepping(t *testing.T) {
  4618  	pluginFixtures := protest.WithPlugins(t, protest.AllNonOptimized, "plugin1/", "plugin2/")
  4619  
  4620  	testseq2Args(".", []string{pluginFixtures[0].Path, pluginFixtures[1].Path}, protest.AllNonOptimized, t, "plugintest2", "", []seqTest{
  4621  		{contContinue, 41},
  4622  		{contStep, "plugin1.go:9"},
  4623  		{contStep, "plugin1.go:10"},
  4624  		{contStep, "plugin1.go:11"},
  4625  		{contNext, "plugin1.go:12"},
  4626  		{contNext, "plugintest2.go:41"},
  4627  		{contNext, "plugintest2.go:42"},
  4628  		{contStep, "plugin2.go:22"},
  4629  		{contNext, "plugin2.go:23"},
  4630  		{contNext, "plugin2.go:26"},
  4631  		{contNext, "plugintest2.go:42"}})
  4632  }
  4633  
  4634  func TestIssue1601(t *testing.T) {
  4635  	protest.MustHaveCgo(t)
  4636  	//Tests that recursive types involving C qualifiers and typedefs are parsed correctly
  4637  	withTestProcess("issue1601", t, func(p *proc.Target, fixture protest.Fixture) {
  4638  		assertNoError(p.Continue(), t, "Continue")
  4639  		evalVariable(p, t, "C.globalq")
  4640  	})
  4641  }
  4642  
  4643  func TestIssue1615(t *testing.T) {
  4644  	// A breakpoint condition that tests for string equality with a constant string shouldn't fail with 'string too long for comparison' error
  4645  
  4646  	withTestProcess("issue1615", t, func(p *proc.Target, fixture protest.Fixture) {
  4647  		bp := setFileBreakpoint(p, t, fixture.Source, 19)
  4648  		bp.UserBreaklet().Cond = &ast.BinaryExpr{
  4649  			Op: token.EQL,
  4650  			X:  &ast.Ident{Name: "s"},
  4651  			Y:  &ast.BasicLit{Kind: token.STRING, Value: `"projects/my-gcp-project-id-string/locations/us-central1/queues/my-task-queue-name"`},
  4652  		}
  4653  
  4654  		assertNoError(p.Continue(), t, "Continue")
  4655  		assertLineNumber(p, t, 19, "")
  4656  	})
  4657  }
  4658  
  4659  func TestCgoStacktrace2(t *testing.T) {
  4660  	skipOn(t, "upstream issue", "windows")
  4661  	skipOn(t, "broken", "386")
  4662  	skipOn(t, "broken", "arm64")
  4663  	protest.MustHaveCgo(t)
  4664  	// If a panic happens during cgo execution the stacktrace should show the C
  4665  	// function that caused the problem.
  4666  	withTestProcess("cgosigsegvstack", t, func(p *proc.Target, fixture protest.Fixture) {
  4667  		p.Continue()
  4668  		frames, err := proc.ThreadStacktrace(p.CurrentThread(), 100)
  4669  		assertNoError(err, t, "Stacktrace()")
  4670  		logStacktrace(t, p, frames)
  4671  		m := stacktraceCheck(t, []string{"C.sigsegv", "C.testfn", "main.main"}, frames)
  4672  		if m == nil {
  4673  			t.Fatal("see previous loglines")
  4674  		}
  4675  	})
  4676  }
  4677  
  4678  func TestIssue1656(t *testing.T) {
  4679  	skipUnlessOn(t, "amd64 only", "amd64")
  4680  	withTestProcess("issue1656/", t, func(p *proc.Target, fixture protest.Fixture) {
  4681  		setFileBreakpoint(p, t, filepath.ToSlash(filepath.Join(fixture.BuildDir, "main.s")), 5)
  4682  		assertNoError(p.Continue(), t, "Continue()")
  4683  		t.Logf("step1\n")
  4684  		assertNoError(p.Step(), t, "Step()")
  4685  		assertLineNumber(p, t, 8, "wrong line number after first step")
  4686  		t.Logf("step2\n")
  4687  		assertNoError(p.Step(), t, "Step()")
  4688  		assertLineNumber(p, t, 9, "wrong line number after second step")
  4689  	})
  4690  }
  4691  
  4692  func TestBreakpointConfusionOnResume(t *testing.T) {
  4693  	// Checks that SetCurrentBreakpoint, (*Thread).StepInstruction and
  4694  	// native.(*Thread).singleStep all agree on which breakpoint the thread is
  4695  	// stopped at.
  4696  	// This test checks for a regression introduced when fixing Issue #1656
  4697  	skipUnlessOn(t, "amd64 only", "amd64")
  4698  	withTestProcess("nopbreakpoint/", t, func(p *proc.Target, fixture protest.Fixture) {
  4699  		maindots := filepath.ToSlash(filepath.Join(fixture.BuildDir, "main.s"))
  4700  		maindotgo := filepath.ToSlash(filepath.Join(fixture.BuildDir, "main.go"))
  4701  		setFileBreakpoint(p, t, maindots, 5) // line immediately after the NOP
  4702  		assertNoError(p.Continue(), t, "First Continue")
  4703  		assertLineNumber(p, t, 5, "not on main.s:5")
  4704  		setFileBreakpoint(p, t, maindots, 4)   // sets a breakpoint on the NOP line, which will be one byte before the breakpoint we currently are stopped at.
  4705  		setFileBreakpoint(p, t, maindotgo, 18) // set one extra breakpoint so that we can recover execution and check the global variable g
  4706  		assertNoError(p.Continue(), t, "Second Continue")
  4707  		gvar := evalVariable(p, t, "g")
  4708  		if n, _ := constant.Int64Val(gvar.Value); n != 1 {
  4709  			t.Fatalf("wrong value of global variable 'g': %v (expected 1)", gvar.Value)
  4710  		}
  4711  	})
  4712  }
  4713  
  4714  func TestIssue1736(t *testing.T) {
  4715  	withTestProcess("testvariables2", t, func(p *proc.Target, fixture protest.Fixture) {
  4716  		assertNoError(p.Continue(), t, "Continue()")
  4717  		ch1BufVar := evalVariable(p, t, "*(ch1.buf)")
  4718  		q := fmt.Sprintf("*(*%q)(%d)", ch1BufVar.DwarfType.Common().Name, ch1BufVar.Addr)
  4719  		t.Logf("%s", q)
  4720  		ch1BufVar2 := evalVariable(p, t, q)
  4721  		if ch1BufVar2.Unreadable != nil {
  4722  			t.Fatal(ch1BufVar2.Unreadable)
  4723  		}
  4724  	})
  4725  }
  4726  
  4727  func TestIssue1817(t *testing.T) {
  4728  	// Setting a breakpoint on a line that doesn't have any PC addresses marked
  4729  	// is_stmt should work.
  4730  	withTestProcess("issue1817", t, func(p *proc.Target, fixture protest.Fixture) {
  4731  		setFileBreakpoint(p, t, fixture.Source, 16)
  4732  	})
  4733  }
  4734  
  4735  func TestListPackagesBuildInfo(t *testing.T) {
  4736  	withTestProcess("pkgrenames", t, func(p *proc.Target, fixture protest.Fixture) {
  4737  		pkgs := p.BinInfo().ListPackagesBuildInfo(true)
  4738  		t.Logf("returned %d", len(pkgs))
  4739  		if len(pkgs) < 10 {
  4740  			t.Errorf("very few packages returned")
  4741  		}
  4742  		for _, pkg := range pkgs {
  4743  			t.Logf("%q %q", pkg.ImportPath, pkg.DirectoryPath)
  4744  			const _fixtures = "_fixtures"
  4745  			fidx := strings.Index(pkg.ImportPath, _fixtures)
  4746  			if fidx < 0 {
  4747  				continue
  4748  			}
  4749  			if !strings.HasSuffix(strings.Replace(pkg.DirectoryPath, "\\", "/", -1), pkg.ImportPath[fidx:]) {
  4750  				t.Errorf("unexpected suffix: %q %q", pkg.ImportPath, pkg.DirectoryPath)
  4751  			}
  4752  		}
  4753  	})
  4754  }
  4755  
  4756  func TestIssue1795(t *testing.T) {
  4757  	// When doing midstack inlining the Go compiler sometimes (always?) emits
  4758  	// the toplevel inlined call with ranges that do not cover the inlining of
  4759  	// other nested inlined calls.
  4760  	// For example if a function A calls B which calls C and both the calls to
  4761  	// B and C are inlined the DW_AT_inlined_subroutine entry for A might have
  4762  	// ranges that do not cover the ranges of the inlined call to C.
  4763  	// This is probably a violation of the DWARF standard (it's unclear) but we
  4764  	// might as well support it as best as possible anyway.
  4765  	if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 13) {
  4766  		t.Skip("Test not relevant to Go < 1.13")
  4767  	}
  4768  	withTestProcessArgs("issue1795", t, ".", []string{}, protest.EnableInlining|protest.EnableOptimization, func(p *proc.Target, fixture protest.Fixture) {
  4769  		assertNoError(p.Continue(), t, "Continue()")
  4770  		assertLineNumber(p, t, 12, "wrong line number after Continue,")
  4771  		assertNoError(p.Next(), t, "Next()")
  4772  		assertLineNumber(p, t, 13, "wrong line number after Next,")
  4773  	})
  4774  	withTestProcessArgs("issue1795", t, ".", []string{}, protest.EnableInlining|protest.EnableOptimization, func(p *proc.Target, fixture protest.Fixture) {
  4775  		setFunctionBreakpoint(p, t, "regexp.(*Regexp).doExecute")
  4776  		assertNoError(p.Continue(), t, "Continue()")
  4777  		assertLineNumber(p, t, 12, "wrong line number after Continue (1),")
  4778  		assertNoError(p.Continue(), t, "Continue()")
  4779  		frames, err := proc.ThreadStacktrace(p.CurrentThread(), 40)
  4780  		assertNoError(err, t, "ThreadStacktrace()")
  4781  		logStacktrace(t, p, frames)
  4782  		if err := checkFrame(frames[0], "regexp.(*Regexp).doExecute", "", 0, false); err != nil {
  4783  			t.Errorf("Wrong frame 0: %v", err)
  4784  		}
  4785  		if err := checkFrame(frames[1], "regexp.(*Regexp).doMatch", "", 0, true); err != nil {
  4786  			t.Errorf("Wrong frame 1: %v", err)
  4787  		}
  4788  		if err := checkFrame(frames[2], "regexp.(*Regexp).MatchString", "", 0, true); err != nil {
  4789  			t.Errorf("Wrong frame 2: %v", err)
  4790  		}
  4791  		if err := checkFrame(frames[3], "main.main", fixture.Source, 12, false); err != nil {
  4792  			t.Errorf("Wrong frame 3: %v", err)
  4793  		}
  4794  	})
  4795  }
  4796  
  4797  func BenchmarkConditionalBreakpoints(b *testing.B) {
  4798  	b.N = 1
  4799  	withTestProcess("issue1549", b, func(p *proc.Target, fixture protest.Fixture) {
  4800  		bp := setFileBreakpoint(p, b, fixture.Source, 12)
  4801  		bp.UserBreaklet().Cond = &ast.BinaryExpr{
  4802  			Op: token.EQL,
  4803  			X:  &ast.Ident{Name: "value"},
  4804  			Y:  &ast.BasicLit{Kind: token.INT, Value: "-1"},
  4805  		}
  4806  		err := p.Continue()
  4807  		if _, exited := err.(proc.ErrProcessExited); !exited {
  4808  			b.Fatalf("Unexpected error on Continue(): %v", err)
  4809  		}
  4810  	})
  4811  }
  4812  
  4813  func TestBackwardNextGeneral(t *testing.T) {
  4814  	if testBackend != "rr" {
  4815  		t.Skip("Reverse stepping test needs rr")
  4816  	}
  4817  	testseq2(t, "testnextprog", "main.helloworld", []seqTest{
  4818  		{contContinue, 13},
  4819  		{contNext, 14},
  4820  		{contReverseNext, 13},
  4821  		{contReverseNext, 34},
  4822  		{contReverseNext, 28},
  4823  		{contReverseNext, 27},
  4824  		{contReverseNext, 26},
  4825  		{contReverseNext, 24},
  4826  		{contReverseNext, 23},
  4827  		{contReverseNext, 31},
  4828  		{contReverseNext, 26},
  4829  		{contReverseNext, 24},
  4830  		{contReverseNext, 23},
  4831  		{contReverseNext, 31},
  4832  		{contReverseNext, 26},
  4833  		{contReverseNext, 24},
  4834  		{contReverseNext, 23},
  4835  		{contReverseNext, 20},
  4836  		{contReverseNext, 19},
  4837  		{contReverseNext, 17},
  4838  		{contReverseNext, 39},
  4839  		{contReverseNext, 38},
  4840  		{contReverseNext, 37},
  4841  	})
  4842  }
  4843  
  4844  func TestBackwardStepOutGeneral(t *testing.T) {
  4845  	if testBackend != "rr" {
  4846  		t.Skip("Reverse stepping test needs rr")
  4847  	}
  4848  	testseq2(t, "testnextprog", "main.helloworld", []seqTest{
  4849  		{contContinue, 13},
  4850  		{contNext, 14},
  4851  		{contReverseStepout, 34},
  4852  		{contReverseStepout, 39},
  4853  	})
  4854  }
  4855  
  4856  func TestBackwardStepGeneral(t *testing.T) {
  4857  	if testBackend != "rr" {
  4858  		t.Skip("Reverse stepping test needs rr")
  4859  	}
  4860  	testseq2(t, "testnextprog", "main.helloworld", []seqTest{
  4861  		{contContinue, 13},
  4862  		{contNext, 14},
  4863  		{contReverseStep, 13},
  4864  		{contReverseStep, 34},
  4865  		{contReverseStep, 28},
  4866  		{contReverseNext, 27}, // skip fmt.Printf
  4867  		{contReverseStep, 26},
  4868  		{contReverseStep, 24},
  4869  		{contReverseStep, 23},
  4870  		{contReverseStep, 11},
  4871  		{contReverseNext, 10}, // skip time.Sleep
  4872  		{contReverseStep, 9},
  4873  
  4874  		{contReverseStep, 31},
  4875  		{contReverseStep, 26},
  4876  		{contReverseStep, 24},
  4877  		{contReverseStep, 23},
  4878  		{contReverseStep, 11},
  4879  		{contReverseNext, 10}, // skip time.Sleep
  4880  		{contReverseStep, 9},
  4881  
  4882  		{contReverseStep, 31},
  4883  		{contReverseStep, 26},
  4884  		{contReverseStep, 24},
  4885  		{contReverseStep, 23},
  4886  		{contReverseStep, 20},
  4887  		{contReverseStep, 19},
  4888  		{contReverseStep, 17},
  4889  		{contReverseStep, 39},
  4890  		{contReverseStep, 38},
  4891  		{contReverseStep, 37},
  4892  	})
  4893  }
  4894  
  4895  func TestBackwardNextDeferPanic(t *testing.T) {
  4896  	if testBackend != "rr" {
  4897  		t.Skip("Reverse stepping test needs rr")
  4898  	}
  4899  	if goversion.VersionAfterOrEqual(runtime.Version(), 1, 18) {
  4900  		testseq2(t, "defercall", "", []seqTest{
  4901  			{contContinue, 12},
  4902  			{contReverseNext, 11},
  4903  			{contReverseNext, 10},
  4904  			{contReverseNext, 9},
  4905  			{contReverseNext, 27},
  4906  
  4907  			{contContinueToBreakpoint, 12}, // skip first call to sampleFunction
  4908  			{contContinueToBreakpoint, 6},  // go to call to sampleFunction through deferreturn
  4909  			{contReverseNext, -1},          // runtime.deferreturn, maybe we should try to skip this
  4910  			{contReverseStepout, 13},
  4911  			{contReverseNext, 12},
  4912  			{contReverseNext, 11},
  4913  			{contReverseNext, 10},
  4914  			{contReverseNext, 9},
  4915  			{contReverseNext, 27},
  4916  
  4917  			{contContinueToBreakpoint, 18}, // go to panic call
  4918  			{contNext, 6},                  // panic so the deferred call happens
  4919  			{contReverseNext, 18},
  4920  			{contReverseNext, 17},
  4921  			{contReverseNext, 16},
  4922  			{contReverseNext, 15},
  4923  			{contReverseNext, 23},
  4924  			{contReverseNext, 22},
  4925  			{contReverseNext, 21},
  4926  			{contReverseNext, 28},
  4927  		})
  4928  	} else {
  4929  		testseq2(t, "defercall", "", []seqTest{
  4930  			{contContinue, 12},
  4931  			{contReverseNext, 11},
  4932  			{contReverseNext, 10},
  4933  			{contReverseNext, 9},
  4934  			{contReverseNext, 27},
  4935  
  4936  			{contContinueToBreakpoint, 12}, // skip first call to sampleFunction
  4937  			{contContinueToBreakpoint, 6},  // go to call to sampleFunction through deferreturn
  4938  			{contReverseNext, 13},
  4939  			{contReverseNext, 12},
  4940  			{contReverseNext, 11},
  4941  			{contReverseNext, 10},
  4942  			{contReverseNext, 9},
  4943  			{contReverseNext, 27},
  4944  
  4945  			{contContinueToBreakpoint, 18}, // go to panic call
  4946  			{contNext, 6},                  // panic so the deferred call happens
  4947  			{contReverseNext, 18},
  4948  			{contReverseNext, 17},
  4949  			{contReverseNext, 16},
  4950  			{contReverseNext, 15},
  4951  			{contReverseNext, 23},
  4952  			{contReverseNext, 22},
  4953  			{contReverseNext, 21},
  4954  			{contReverseNext, 28},
  4955  		})
  4956  	}
  4957  }
  4958  
  4959  func TestIssue1925(t *testing.T) {
  4960  	// Calling a function should not leave cached goroutine information in an
  4961  	// inconsistent state.
  4962  	// In particular the stepInstructionOut function called at the end of a
  4963  	// 'call' procedure should clean the G cache like every other function
  4964  	// altering the state of the target process.
  4965  	protest.MustSupportFunctionCalls(t, testBackend)
  4966  	withTestProcess("testvariables2", t, func(p *proc.Target, fixture protest.Fixture) {
  4967  		assertNoError(p.Continue(), t, "Continue()")
  4968  		assertNoError(proc.EvalExpressionWithCalls(p, p.SelectedGoroutine(), "afunc(2)", normalLoadConfig, true), t, "Call")
  4969  		t.Logf("%v\n", p.SelectedGoroutine().CurrentLoc)
  4970  		if loc := p.SelectedGoroutine().CurrentLoc; loc.File != fixture.Source {
  4971  			t.Errorf("wrong location for selected goroutine after call: %s:%d", loc.File, loc.Line)
  4972  		}
  4973  	})
  4974  }
  4975  
  4976  func TestStepIntoWrapperForEmbeddedPointer(t *testing.T) {
  4977  	skipOn(t, "N/A", "linux", "386", "pie") // skipping wrappers doesn't work on linux/386/PIE due to the use of get_pc_thunk
  4978  	// Under some circumstances (when using an interface to call a method on an
  4979  	// embedded field, see _fixtures/ifaceembcall.go) the compiler will
  4980  	// autogenerate a wrapper function that uses a tail call (i.e. it ends in
  4981  	// an unconditional jump instruction to a different function).
  4982  	// Delve should be able to step into this tail call.
  4983  	testseq2(t, "ifaceembcall", "", []seqTest{
  4984  		{contContinue, 28}, // main.main, the line calling iface.PtrReceiver()
  4985  		{contStep, 18},     // main.(*A).PtrReceiver
  4986  		{contStep, 19},
  4987  		{contStepout, 28},
  4988  		{contContinueToBreakpoint, 29}, // main.main, the line calling iface.NonPtrReceiver()
  4989  		{contStep, 22},                 // main.(A).NonPtrReceiver
  4990  		{contStep, 23},
  4991  		{contStepout, 29}})
  4992  
  4993  	// same test but with next instead of stepout
  4994  	if goversion.VersionAfterOrEqual(runtime.Version(), 1, 14) && runtime.GOARCH != "386" && !goversion.VersionAfterOrEqualRev(runtime.Version(), 1, 15, 4) {
  4995  		// Line numbers generated for versions 1.14 through 1.15.3 on any system except linux/386
  4996  		testseq2(t, "ifaceembcall", "", []seqTest{
  4997  			{contContinue, 28}, // main.main, the line calling iface.PtrReceiver()
  4998  			{contStep, 18},     // main.(*A).PtrReceiver
  4999  			{contNext, 19},
  5000  			{contNext, 19},
  5001  			{contNext, 28},
  5002  			{contContinueToBreakpoint, 29}, // main.main, the line calling iface.NonPtrReceiver()
  5003  			{contStep, 22},
  5004  			{contNext, 23},
  5005  			{contNext, 23},
  5006  			{contNext, 29}})
  5007  	} else {
  5008  		testseq2(t, "ifaceembcall", "", []seqTest{
  5009  			{contContinue, 28}, // main.main, the line calling iface.PtrReceiver()
  5010  			{contStep, 18},     // main.(*A).PtrReceiver
  5011  			{contNext, 19},
  5012  			{contNext, 28},
  5013  			{contContinueToBreakpoint, 29}, // main.main, the line calling iface.NonPtrReceiver()
  5014  			{contStep, 22},
  5015  			{contNext, 23},
  5016  			{contNext, 29}})
  5017  
  5018  	}
  5019  }
  5020  
  5021  func TestRefreshCurThreadSelGAfterContinueOnceError(t *testing.T) {
  5022  	// Issue #2078:
  5023  	// Tests that on macOS/lldb the current thread/selected goroutine are
  5024  	// refreshed after ContinueOnce returns an error due to a segmentation
  5025  	// fault.
  5026  
  5027  	skipUnlessOn(t, "N/A", "darwin", "lldb")
  5028  
  5029  	withTestProcess("issue2078", t, func(p *proc.Target, fixture protest.Fixture) {
  5030  		setFileBreakpoint(p, t, fixture.Source, 4)
  5031  		assertNoError(p.Continue(), t, "Continue() (first)")
  5032  		if p.Continue() == nil {
  5033  			t.Fatalf("Second continue did not return an error")
  5034  		}
  5035  		g := p.SelectedGoroutine()
  5036  		if g.CurrentLoc.Line != 9 {
  5037  			t.Fatalf("wrong current location %s:%d (expected :9)", g.CurrentLoc.File, g.CurrentLoc.Line)
  5038  		}
  5039  	})
  5040  }
  5041  
  5042  func TestStepoutOneliner(t *testing.T) {
  5043  	// The heuristic detecting autogenerated wrappers when stepping out should
  5044  	// not skip oneliner functions.
  5045  	withTestProcess("issue2086", t, func(p *proc.Target, fixture protest.Fixture) {
  5046  		assertNoError(p.Continue(), t, "Continue()")
  5047  		assertLineNumber(p, t, 15, "after first continue")
  5048  		assertNoError(p.StepOut(), t, "StepOut()")
  5049  		if fn := p.BinInfo().PCToFunc(currentPC(p, t)); fn == nil || fn.Name != "main.T.m" {
  5050  			t.Fatalf("wrong function after stepout %#v", fn)
  5051  		}
  5052  		assertNoError(p.StepOut(), t, "second StepOut()")
  5053  		if fn := p.BinInfo().PCToFunc(currentPC(p, t)); fn == nil || fn.Name != "main.main" {
  5054  			t.Fatalf("wrong fnuction after second stepout %#v", fn)
  5055  		}
  5056  	})
  5057  }
  5058  
  5059  func TestRequestManualStopWhileStopped(t *testing.T) {
  5060  	// Requesting a manual stop while stopped shouldn't cause problems (issue #2138).
  5061  	withTestProcess("issue2138", t, func(p *proc.Target, fixture protest.Fixture) {
  5062  		resumed := make(chan struct{})
  5063  		setFileBreakpoint(p, t, fixture.Source, 8)
  5064  		assertNoError(p.Continue(), t, "Continue() 1")
  5065  		p.ResumeNotify(resumed)
  5066  		go func() {
  5067  			<-resumed
  5068  			time.Sleep(1 * time.Second)
  5069  			p.RequestManualStop()
  5070  		}()
  5071  		t.Logf("at time.Sleep call")
  5072  		assertNoError(p.Continue(), t, "Continue() 2")
  5073  		t.Logf("manually stopped")
  5074  		p.RequestManualStop()
  5075  		p.RequestManualStop()
  5076  		p.RequestManualStop()
  5077  
  5078  		resumed = make(chan struct{})
  5079  		p.ResumeNotify(resumed)
  5080  		go func() {
  5081  			<-resumed
  5082  			time.Sleep(1 * time.Second)
  5083  			p.RequestManualStop()
  5084  		}()
  5085  		t.Logf("resuming sleep")
  5086  		assertNoError(p.Continue(), t, "Continue() 3")
  5087  		t.Logf("done")
  5088  	})
  5089  }
  5090  
  5091  func TestStepOutPreservesGoroutine(t *testing.T) {
  5092  	// Checks that StepOut preserves the currently selected goroutine.
  5093  	skipOn(t, "broken", "freebsd")
  5094  	rand.Seed(time.Now().Unix())
  5095  	withTestProcess("issue2113", t, func(p *proc.Target, fixture protest.Fixture) {
  5096  		assertNoError(p.Continue(), t, "Continue()")
  5097  
  5098  		logState := func() {
  5099  			g := p.SelectedGoroutine()
  5100  			var goid int = -42
  5101  			if g != nil {
  5102  				goid = g.ID
  5103  			}
  5104  			pc := currentPC(p, t)
  5105  			f, l, fn := p.BinInfo().PCToLine(pc)
  5106  			var fnname string = "???"
  5107  			if fn != nil {
  5108  				fnname = fn.Name
  5109  			}
  5110  			t.Logf("goroutine %d at %s:%d in %s", goid, f, l, fnname)
  5111  		}
  5112  
  5113  		logState()
  5114  
  5115  		gs, _, err := proc.GoroutinesInfo(p, 0, 0)
  5116  		assertNoError(err, t, "GoroutinesInfo")
  5117  		candg := []*proc.G{}
  5118  		bestg := []*proc.G{}
  5119  		for _, g := range gs {
  5120  			frames, err := g.Stacktrace(20, 0)
  5121  			assertNoError(err, t, "Stacktrace")
  5122  			for _, frame := range frames {
  5123  				if frame.Call.Fn != nil && frame.Call.Fn.Name == "main.coroutine" {
  5124  					candg = append(candg, g)
  5125  					if g.Thread != nil && frames[0].Call.Fn != nil && strings.HasPrefix(frames[0].Call.Fn.Name, "runtime.") {
  5126  						bestg = append(bestg, g)
  5127  					}
  5128  					break
  5129  				}
  5130  			}
  5131  		}
  5132  		var pickg *proc.G
  5133  		if len(bestg) > 0 {
  5134  			pickg = bestg[rand.Intn(len(bestg))]
  5135  			t.Logf("selected goroutine %d (best)\n", pickg.ID)
  5136  		} else {
  5137  			pickg = candg[rand.Intn(len(candg))]
  5138  			t.Logf("selected goroutine %d\n", pickg.ID)
  5139  
  5140  		}
  5141  		goid := pickg.ID
  5142  		assertNoError(p.SwitchGoroutine(pickg), t, "SwitchGoroutine")
  5143  
  5144  		logState()
  5145  
  5146  		err = p.StepOut()
  5147  		if err != nil {
  5148  			_, isexited := err.(proc.ErrProcessExited)
  5149  			if !isexited {
  5150  				assertNoError(err, t, "StepOut()")
  5151  			} else {
  5152  				return
  5153  			}
  5154  		}
  5155  
  5156  		logState()
  5157  
  5158  		g2 := p.SelectedGoroutine()
  5159  		if g2 == nil {
  5160  			t.Fatalf("no selected goroutine after stepout")
  5161  		} else if g2.ID != goid {
  5162  			t.Fatalf("unexpected selected goroutine %d", g2.ID)
  5163  		}
  5164  	})
  5165  }
  5166  
  5167  func TestIssue2319(t *testing.T) {
  5168  	// Check to make sure we don't crash on startup when the target is
  5169  	// a binary with a mix of DWARF-5 C++ compilation units and
  5170  	// DWARF-4 Go compilation units.
  5171  
  5172  	// Require CGO, since we need to use the external linker for this test.
  5173  	protest.MustHaveCgo(t)
  5174  
  5175  	// The test fixture uses linux/amd64 assembly and a *.syso file
  5176  	// that is linux/amd64, so skip for other architectures.
  5177  	if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
  5178  		t.Skipf("skipping since not linux/amd64")
  5179  	}
  5180  
  5181  	// Skip unless on 1.14 or later. The test fixture uses a *.syso
  5182  	// file, which in 1.13 is not loaded unless we're in internal
  5183  	// linking mode (we need external linking here).
  5184  	if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 14) {
  5185  		t.Skip("test contains fixture that is specific to go 1.14+")
  5186  	}
  5187  
  5188  	fixture := protest.BuildFixture("issue2319/", protest.BuildModeExternalLinker)
  5189  
  5190  	// Load up the binary and make sure there are no crashes.
  5191  	bi := proc.NewBinaryInfo("linux", "amd64")
  5192  	assertNoError(bi.LoadBinaryInfo(fixture.Path, 0, nil), t, "LoadBinaryInfo")
  5193  }
  5194  
  5195  func TestDump(t *testing.T) {
  5196  	if runtime.GOOS == "freebsd" || (runtime.GOOS == "darwin" && testBackend == "native") {
  5197  		t.Skip("not supported")
  5198  	}
  5199  
  5200  	convertRegisters := func(arch *proc.Arch, dregs op.DwarfRegisters) string {
  5201  		dregs.Reg(^uint64(0))
  5202  		buf := new(bytes.Buffer)
  5203  		for i := 0; i < dregs.CurrentSize(); i++ {
  5204  			reg := dregs.Reg(uint64(i))
  5205  			if reg == nil {
  5206  				continue
  5207  			}
  5208  			name, _, repr := arch.DwarfRegisterToString(i, reg)
  5209  			fmt.Fprintf(buf, " %s=%s", name, repr)
  5210  		}
  5211  		return buf.String()
  5212  	}
  5213  
  5214  	convertThread := func(thread proc.Thread) string {
  5215  		regs, err := thread.Registers()
  5216  		assertNoError(err, t, fmt.Sprintf("Thread registers %d", thread.ThreadID()))
  5217  		arch := thread.BinInfo().Arch
  5218  		dregs := arch.RegistersToDwarfRegisters(0, regs)
  5219  		return fmt.Sprintf("%08d %s", thread.ThreadID(), convertRegisters(arch, *dregs))
  5220  	}
  5221  
  5222  	convertThreads := func(threads []proc.Thread) []string {
  5223  		r := make([]string, len(threads))
  5224  		for i := range threads {
  5225  			r[i] = convertThread(threads[i])
  5226  		}
  5227  		sort.Strings(r)
  5228  		return r
  5229  	}
  5230  
  5231  	convertGoroutine := func(g *proc.G) string {
  5232  		threadID := 0
  5233  		if g.Thread != nil {
  5234  			threadID = g.Thread.ThreadID()
  5235  		}
  5236  		return fmt.Sprintf("%d pc=%#x sp=%#x bp=%#x lr=%#x gopc=%#x startpc=%#x systemstack=%v thread=%d", g.ID, g.PC, g.SP, g.BP, g.LR, g.GoPC, g.StartPC, g.SystemStack, threadID)
  5237  	}
  5238  
  5239  	convertFrame := func(arch *proc.Arch, frame *proc.Stackframe) string {
  5240  		return fmt.Sprintf("currentPC=%#x callPC=%#x frameOff=%#x\n", frame.Current.PC, frame.Call.PC, frame.FrameOffset())
  5241  	}
  5242  
  5243  	makeDump := func(p *proc.Target, corePath, exePath string, flags proc.DumpFlags) *proc.Target {
  5244  		fh, err := os.Create(corePath)
  5245  		assertNoError(err, t, "Create()")
  5246  		var state proc.DumpState
  5247  		p.Dump(fh, flags, &state)
  5248  		assertNoError(state.Err, t, "Dump()")
  5249  		if state.ThreadsDone != state.ThreadsTotal || state.MemDone != state.MemTotal || !state.AllDone || state.Dumping || state.Canceled {
  5250  			t.Fatalf("bad DumpState %#v", &state)
  5251  		}
  5252  		c, err := core.OpenCore(corePath, exePath, nil)
  5253  		assertNoError(err, t, "OpenCore()")
  5254  		return c
  5255  	}
  5256  
  5257  	testDump := func(p, c *proc.Target) {
  5258  		if p.Pid() != c.Pid() {
  5259  			t.Errorf("Pid mismatch %x %x", p.Pid(), c.Pid())
  5260  		}
  5261  
  5262  		threads := convertThreads(p.ThreadList())
  5263  		cthreads := convertThreads(c.ThreadList())
  5264  
  5265  		if len(threads) != len(cthreads) {
  5266  			t.Errorf("Thread number mismatch %d %d", len(threads), len(cthreads))
  5267  		}
  5268  
  5269  		for i := range threads {
  5270  			if threads[i] != cthreads[i] {
  5271  				t.Errorf("Thread mismatch\nlive:\t%s\ncore:\t%s", threads[i], cthreads[i])
  5272  			}
  5273  		}
  5274  
  5275  		gos, _, err := proc.GoroutinesInfo(p, 0, 0)
  5276  		assertNoError(err, t, "GoroutinesInfo() - live process")
  5277  		cgos, _, err := proc.GoroutinesInfo(c, 0, 0)
  5278  		assertNoError(err, t, "GoroutinesInfo() - core dump")
  5279  
  5280  		if len(gos) != len(cgos) {
  5281  			t.Errorf("Goroutine number mismatch %d %d", len(gos), len(cgos))
  5282  		}
  5283  
  5284  		var scope, cscope *proc.EvalScope
  5285  
  5286  		for i := range gos {
  5287  			if convertGoroutine(gos[i]) != convertGoroutine(cgos[i]) {
  5288  				t.Errorf("Goroutine mismatch\nlive:\t%s\ncore:\t%s", convertGoroutine(gos[i]), convertGoroutine(cgos[i]))
  5289  			}
  5290  
  5291  			frames, err := gos[i].Stacktrace(20, 0)
  5292  			assertNoError(err, t, fmt.Sprintf("Stacktrace for goroutine %d - live process", gos[i].ID))
  5293  			cframes, err := cgos[i].Stacktrace(20, 0)
  5294  			assertNoError(err, t, fmt.Sprintf("Stacktrace for goroutine %d - core dump", gos[i].ID))
  5295  
  5296  			if len(frames) != len(cframes) {
  5297  				t.Errorf("Frame number mismatch for goroutine %d: %d %d", gos[i].ID, len(frames), len(cframes))
  5298  			}
  5299  
  5300  			for j := range frames {
  5301  				if convertFrame(p.BinInfo().Arch, &frames[j]) != convertFrame(p.BinInfo().Arch, &cframes[j]) {
  5302  					t.Errorf("Frame mismatch %d.%d\nlive:\t%s\ncore:\t%s", gos[i].ID, j, convertFrame(p.BinInfo().Arch, &frames[j]), convertFrame(p.BinInfo().Arch, &cframes[j]))
  5303  				}
  5304  				if frames[j].Call.Fn != nil && frames[j].Call.Fn.Name == "main.main" {
  5305  					scope = proc.FrameToScope(p, p.Memory(), gos[i], frames[j:]...)
  5306  					cscope = proc.FrameToScope(c, c.Memory(), cgos[i], cframes[j:]...)
  5307  				}
  5308  			}
  5309  		}
  5310  
  5311  		vars, err := scope.LocalVariables(normalLoadConfig)
  5312  		assertNoError(err, t, "LocalVariables - live process")
  5313  		cvars, err := cscope.LocalVariables(normalLoadConfig)
  5314  		assertNoError(err, t, "LocalVariables - core dump")
  5315  
  5316  		if len(vars) != len(cvars) {
  5317  			t.Errorf("Variable number mismatch %d %d", len(vars), len(cvars))
  5318  		}
  5319  
  5320  		for i := range vars {
  5321  			varstr := vars[i].Name + "=" + api.ConvertVar(vars[i]).SinglelineString()
  5322  			cvarstr := cvars[i].Name + "=" + api.ConvertVar(cvars[i]).SinglelineString()
  5323  			if strings.Contains(varstr, "(unreadable") {
  5324  				// errors reading from unmapped memory differ between live process and core
  5325  				continue
  5326  			}
  5327  			if varstr != cvarstr {
  5328  				t.Errorf("Variable mismatch %s %s", varstr, cvarstr)
  5329  			}
  5330  		}
  5331  	}
  5332  
  5333  	withTestProcess("testvariables2", t, func(p *proc.Target, fixture protest.Fixture) {
  5334  		assertNoError(p.Continue(), t, "Continue()")
  5335  		corePath := filepath.Join(fixture.BuildDir, "coredump")
  5336  		corePathPlatIndep := filepath.Join(fixture.BuildDir, "coredump-indep")
  5337  
  5338  		t.Logf("testing normal dump")
  5339  
  5340  		c := makeDump(p, corePath, fixture.Path, 0)
  5341  		defer os.Remove(corePath)
  5342  		testDump(p, c)
  5343  
  5344  		if runtime.GOOS == "linux" && runtime.GOARCH == "amd64" {
  5345  			// No reason to do this test on other goos/goarch because they use the
  5346  			// platform-independent format anyway.
  5347  			t.Logf("testing platform-independent dump")
  5348  			c2 := makeDump(p, corePathPlatIndep, fixture.Path, proc.DumpPlatformIndependent)
  5349  			defer os.Remove(corePathPlatIndep)
  5350  			testDump(p, c2)
  5351  		}
  5352  	})
  5353  }
  5354  
  5355  func TestCompositeMemoryWrite(t *testing.T) {
  5356  	if runtime.GOARCH != "amd64" {
  5357  		t.Skip("only valid on amd64")
  5358  	}
  5359  	skipOn(t, "not implemented", "freebsd")
  5360  	withTestProcess("fputest/", t, func(p *proc.Target, fixture protest.Fixture) {
  5361  		getregs := func() (pc, rax, xmm1 uint64) {
  5362  			regs, err := p.CurrentThread().Registers()
  5363  			assertNoError(err, t, "Registers")
  5364  			fmtregs, err := regs.Slice(true)
  5365  			assertNoError(err, t, "register slice")
  5366  
  5367  			var xmm1buf []byte
  5368  
  5369  			for _, reg := range fmtregs {
  5370  				switch strings.ToLower(reg.Name) {
  5371  				case "rax":
  5372  					rax = reg.Reg.Uint64Val
  5373  				case "xmm1":
  5374  					xmm1buf = reg.Reg.Bytes
  5375  				}
  5376  			}
  5377  
  5378  			xmm1 = binary.LittleEndian.Uint64(xmm1buf[:8])
  5379  
  5380  			return regs.PC(), rax, xmm1
  5381  		}
  5382  
  5383  		const fakeAddress = 0xbeef0000
  5384  
  5385  		getmem := func(mem proc.MemoryReader) uint64 {
  5386  			buf := make([]byte, 8)
  5387  			_, err := mem.ReadMemory(buf, fakeAddress)
  5388  			assertNoError(err, t, "ReadMemory")
  5389  			return binary.LittleEndian.Uint64(buf)
  5390  		}
  5391  
  5392  		assertNoError(p.Continue(), t, "Continue()")
  5393  		oldPc, oldRax, oldXmm1 := getregs()
  5394  		t.Logf("PC %#x AX %#x XMM1 %#x", oldPc, oldRax, oldXmm1)
  5395  
  5396  		memRax, err := proc.NewCompositeMemory(p, []op.Piece{{Size: 0, Val: 0, Kind: op.RegPiece}}, fakeAddress)
  5397  		assertNoError(err, t, "NewCompositeMemory (rax)")
  5398  		memXmm1, err := proc.NewCompositeMemory(p, []op.Piece{{Size: 0, Val: 18, Kind: op.RegPiece}}, fakeAddress)
  5399  		assertNoError(err, t, "NewCompositeMemory (xmm1)")
  5400  
  5401  		if memRax := getmem(memRax); memRax != oldRax {
  5402  			t.Errorf("reading rax memory, expected %#x got %#x", oldRax, memRax)
  5403  		}
  5404  		if memXmm1 := getmem(memXmm1); memXmm1 != oldXmm1 {
  5405  			t.Errorf("reading xmm1 memory, expected %#x got %#x", oldXmm1, memXmm1)
  5406  		}
  5407  
  5408  		_, err = memRax.WriteMemory(0xbeef0000, []byte{0xef, 0xbe, 0x0d, 0xf0, 0xef, 0xbe, 0x0d, 0xf0})
  5409  		assertNoError(err, t, "WriteMemory (rax)")
  5410  		_, err = memXmm1.WriteMemory(0xbeef0000, []byte{0xef, 0xbe, 0x0d, 0xf0, 0xef, 0xbe, 0x0d, 0xf0})
  5411  		assertNoError(err, t, "WriteMemory (xmm1)")
  5412  
  5413  		newPc, newRax, newXmm1 := getregs()
  5414  		t.Logf("PC %#x AX %#x XMM1 %#x", newPc, newRax, newXmm1)
  5415  
  5416  		const tgt = 0xf00dbeeff00dbeef
  5417  		if newRax != tgt {
  5418  			t.Errorf("reading rax register, expected %#x, got %#x", uint64(tgt), newRax)
  5419  		}
  5420  		if newXmm1 != tgt {
  5421  			t.Errorf("reading xmm1 register, expected %#x, got %#x", uint64(tgt), newXmm1)
  5422  		}
  5423  	})
  5424  }
  5425  
  5426  func TestVariablesWithExternalLinking(t *testing.T) {
  5427  	protest.MustHaveCgo(t)
  5428  	// Tests that macOSDebugFrameBugWorkaround works.
  5429  	// See:
  5430  	//  https://github.com/golang/go/issues/25841
  5431  	//  https://github.com/go-delve/delve/issues/2346
  5432  	withTestProcessArgs("testvariables2", t, ".", []string{}, protest.BuildModeExternalLinker, func(p *proc.Target, fixture protest.Fixture) {
  5433  		assertNoError(p.Continue(), t, "Continue()")
  5434  		str1Var := evalVariable(p, t, "str1")
  5435  		if str1Var.Unreadable != nil {
  5436  			t.Fatalf("variable str1 is unreadable: %v", str1Var.Unreadable)
  5437  		}
  5438  		t.Logf("%#v", str1Var)
  5439  		if constant.StringVal(str1Var.Value) != "01234567890" {
  5440  			t.Fatalf("wrong value for str1: %v", str1Var.Value)
  5441  		}
  5442  	})
  5443  }
  5444  
  5445  func TestWatchpointsBasic(t *testing.T) {
  5446  	skipOn(t, "not implemented", "freebsd")
  5447  	skipOn(t, "not implemented", "386")
  5448  	skipOn(t, "see https://github.com/go-delve/delve/issues/2768", "windows")
  5449  	protest.AllowRecording(t)
  5450  
  5451  	position1 := 19
  5452  	position5 := 41
  5453  
  5454  	if runtime.GOARCH == "arm64" {
  5455  		position1 = 18
  5456  		position5 = 40
  5457  	}
  5458  
  5459  	withTestProcess("databpeasy", t, func(p *proc.Target, fixture protest.Fixture) {
  5460  		setFunctionBreakpoint(p, t, "main.main")
  5461  		setFileBreakpoint(p, t, fixture.Source, 21) // Position 2 breakpoint
  5462  		setFileBreakpoint(p, t, fixture.Source, 27) // Position 4 breakpoint
  5463  		assertNoError(p.Continue(), t, "Continue 0")
  5464  		assertLineNumber(p, t, 13, "Continue 0") // Position 0
  5465  
  5466  		scope, err := proc.GoroutineScope(p, p.CurrentThread())
  5467  		assertNoError(err, t, "GoroutineScope")
  5468  
  5469  		bp, err := p.SetWatchpoint(0, scope, "globalvar1", proc.WatchWrite, nil)
  5470  		assertNoError(err, t, "SetDataBreakpoint(write-only)")
  5471  
  5472  		assertNoError(p.Continue(), t, "Continue 1")
  5473  		assertLineNumber(p, t, position1, "Continue 1") // Position 1
  5474  
  5475  		if curbp := p.CurrentThread().Breakpoint().Breakpoint; curbp == nil || (curbp.LogicalID() != bp.LogicalID()) {
  5476  			t.Fatal("breakpoint not set")
  5477  		}
  5478  
  5479  		assertNoError(p.ClearBreakpoint(bp.Addr), t, "ClearBreakpoint")
  5480  
  5481  		assertNoError(p.Continue(), t, "Continue 2")
  5482  		assertLineNumber(p, t, 21, "Continue 2") // Position 2
  5483  
  5484  		_, err = p.SetWatchpoint(0, scope, "globalvar1", proc.WatchWrite|proc.WatchRead, nil)
  5485  		assertNoError(err, t, "SetDataBreakpoint(read-write)")
  5486  
  5487  		assertNoError(p.Continue(), t, "Continue 3")
  5488  		assertLineNumber(p, t, 22, "Continue 3") // Position 3
  5489  
  5490  		p.ClearBreakpoint(bp.Addr)
  5491  
  5492  		assertNoError(p.Continue(), t, "Continue 4")
  5493  		assertLineNumber(p, t, 27, "Continue 4") // Position 4
  5494  
  5495  		t.Logf("setting final breakpoint")
  5496  		_, err = p.SetWatchpoint(0, scope, "globalvar1", proc.WatchWrite, nil)
  5497  		assertNoError(err, t, "SetDataBreakpoint(write-only, again)")
  5498  
  5499  		assertNoError(p.Continue(), t, "Continue 5")
  5500  		assertLineNumber(p, t, position5, "Continue 5") // Position 5
  5501  	})
  5502  }
  5503  
  5504  func TestWatchpointCounts(t *testing.T) {
  5505  	skipOn(t, "not implemented", "freebsd")
  5506  	skipOn(t, "not implemented", "386")
  5507  	skipOn(t, "see https://github.com/go-delve/delve/issues/2768", "windows")
  5508  	protest.AllowRecording(t)
  5509  
  5510  	withTestProcess("databpcountstest", t, func(p *proc.Target, fixture protest.Fixture) {
  5511  		setFunctionBreakpoint(p, t, "main.main")
  5512  		assertNoError(p.Continue(), t, "Continue 0")
  5513  
  5514  		scope, err := proc.GoroutineScope(p, p.CurrentThread())
  5515  		assertNoError(err, t, "GoroutineScope")
  5516  
  5517  		bp, err := p.SetWatchpoint(0, scope, "globalvar1", proc.WatchWrite, nil)
  5518  		assertNoError(err, t, "SetWatchpoint(write-only)")
  5519  
  5520  		for {
  5521  			if err := p.Continue(); err != nil {
  5522  				if _, exited := err.(proc.ErrProcessExited); exited {
  5523  					break
  5524  				}
  5525  				assertNoError(err, t, "Continue()")
  5526  			}
  5527  		}
  5528  
  5529  		t.Logf("TotalHitCount: %d", bp.Logical.TotalHitCount)
  5530  		if bp.Logical.TotalHitCount != 200 {
  5531  			t.Fatalf("Wrong TotalHitCount for the breakpoint (%d)", bp.Logical.TotalHitCount)
  5532  		}
  5533  
  5534  		if len(bp.Logical.HitCount) != 2 {
  5535  			t.Fatalf("Wrong number of goroutines for breakpoint (%d)", len(bp.Logical.HitCount))
  5536  		}
  5537  
  5538  		for _, v := range bp.Logical.HitCount {
  5539  			if v != 100 {
  5540  				t.Fatalf("Wrong HitCount for breakpoint (%v)", bp.Logical.HitCount)
  5541  			}
  5542  		}
  5543  	})
  5544  }
  5545  
  5546  func TestManualStopWhileStopped(t *testing.T) {
  5547  	// Checks that RequestManualStop sent to a stopped thread does not cause the target process to die.
  5548  	withTestProcess("loopprog", t, func(p *proc.Target, fixture protest.Fixture) {
  5549  		asyncCont := func(done chan struct{}) {
  5550  			defer close(done)
  5551  			err := p.Continue()
  5552  			t.Logf("%v\n", err)
  5553  			if err != nil {
  5554  				panic(err)
  5555  			}
  5556  			for _, th := range p.ThreadList() {
  5557  				if th.Breakpoint().Breakpoint != nil {
  5558  					t.Logf("unexpected stop at breakpoint: %v", th.Breakpoint().Breakpoint)
  5559  					panic("unexpected stop at breakpoint")
  5560  				}
  5561  			}
  5562  		}
  5563  
  5564  		const (
  5565  			repeatsSlow = 3
  5566  			repeatsFast = 5
  5567  		)
  5568  
  5569  		for i := 0; i < repeatsSlow; i++ {
  5570  			t.Logf("Continue %d (slow)", i)
  5571  			done := make(chan struct{})
  5572  			go asyncCont(done)
  5573  			time.Sleep(1 * time.Second)
  5574  			p.RequestManualStop()
  5575  			time.Sleep(1 * time.Second)
  5576  			p.RequestManualStop()
  5577  			time.Sleep(1 * time.Second)
  5578  			<-done
  5579  		}
  5580  		for i := 0; i < repeatsFast; i++ {
  5581  			t.Logf("Continue %d (fast)", i)
  5582  			rch := make(chan struct{})
  5583  			done := make(chan struct{})
  5584  			p.ResumeNotify(rch)
  5585  			go asyncCont(done)
  5586  			<-rch
  5587  			p.RequestManualStop()
  5588  			p.RequestManualStop()
  5589  			<-done
  5590  		}
  5591  	})
  5592  }
  5593  
  5594  func TestDwrapStartLocation(t *testing.T) {
  5595  	// Tests that the start location of a goroutine is unwrapped in Go 1.17 and later.
  5596  	withTestProcess("goroutinestackprog", t, func(p *proc.Target, fixture protest.Fixture) {
  5597  		setFunctionBreakpoint(p, t, "main.stacktraceme")
  5598  		assertNoError(p.Continue(), t, "Continue()")
  5599  		gs, _, err := proc.GoroutinesInfo(p, 0, 0)
  5600  		assertNoError(err, t, "GoroutinesInfo")
  5601  		found := false
  5602  		for _, g := range gs {
  5603  			startLoc := g.StartLoc(p)
  5604  			if startLoc.Fn == nil {
  5605  				continue
  5606  			}
  5607  			t.Logf("%#v\n", startLoc.Fn.Name)
  5608  			if startLoc.Fn.Name == "main.agoroutine" {
  5609  				found = true
  5610  				break
  5611  			}
  5612  		}
  5613  		if !found {
  5614  			t.Errorf("could not find any goroutine with a start location of main.agoroutine")
  5615  		}
  5616  	})
  5617  }
  5618  
  5619  func TestWatchpointStack(t *testing.T) {
  5620  	skipOn(t, "not implemented", "freebsd")
  5621  	skipOn(t, "not implemented", "386")
  5622  	skipOn(t, "see https://github.com/go-delve/delve/issues/2768", "windows")
  5623  	protest.AllowRecording(t)
  5624  
  5625  	position1 := 17
  5626  
  5627  	if runtime.GOARCH == "arm64" {
  5628  		position1 = 16
  5629  	}
  5630  
  5631  	withTestProcess("databpstack", t, func(p *proc.Target, fixture protest.Fixture) {
  5632  		setFileBreakpoint(p, t, fixture.Source, 11) // Position 0 breakpoint
  5633  		clearlen := len(p.Breakpoints().M)
  5634  
  5635  		assertNoError(p.Continue(), t, "Continue 0")
  5636  		assertLineNumber(p, t, 11, "Continue 0") // Position 0
  5637  
  5638  		scope, err := proc.GoroutineScope(p, p.CurrentThread())
  5639  		assertNoError(err, t, "GoroutineScope")
  5640  
  5641  		_, err = p.SetWatchpoint(0, scope, "w", proc.WatchWrite, nil)
  5642  		assertNoError(err, t, "SetDataBreakpoint(write-only)")
  5643  
  5644  		watchbpnum := 3
  5645  		if recorded, _ := p.Recorded(); recorded {
  5646  			watchbpnum = 4
  5647  		}
  5648  
  5649  		if len(p.Breakpoints().M) != clearlen+watchbpnum {
  5650  			// want 1 watchpoint, 1 stack resize breakpoint, 1 out of scope sentinel (2 if recorded)
  5651  			t.Errorf("wrong number of breakpoints after setting watchpoint: %d", len(p.Breakpoints().M)-clearlen)
  5652  		}
  5653  
  5654  		var retaddr uint64
  5655  		for _, bp := range p.Breakpoints().M {
  5656  			for _, breaklet := range bp.Breaklets {
  5657  				if breaklet.Kind&proc.WatchOutOfScopeBreakpoint != 0 {
  5658  					retaddr = bp.Addr
  5659  					break
  5660  				}
  5661  			}
  5662  		}
  5663  
  5664  		// Note: for recorded processes retaddr will not always be the return
  5665  		// address, ~50% of the times it will be the address of the CALL
  5666  		// instruction preceding the return address, this does not matter for this
  5667  		// test.
  5668  
  5669  		_, err = p.SetBreakpoint(0, retaddr, proc.UserBreakpoint, nil)
  5670  		assertNoError(err, t, "SetBreakpoint")
  5671  
  5672  		if len(p.Breakpoints().M) != clearlen+watchbpnum {
  5673  			// want 1 watchpoint, 1 stack resize breakpoint, 1 out of scope sentinel (which is also a user breakpoint) (and another out of scope sentinel if recorded)
  5674  			t.Errorf("wrong number of breakpoints after setting watchpoint: %d", len(p.Breakpoints().M)-clearlen)
  5675  		}
  5676  
  5677  		assertNoError(p.Continue(), t, "Continue 1")
  5678  		assertLineNumber(p, t, position1, "Continue 1") // Position 1
  5679  
  5680  		assertNoError(p.Continue(), t, "Continue 2")
  5681  		t.Logf("%#v", p.CurrentThread().Breakpoint().Breakpoint)
  5682  		assertLineNumber(p, t, 24, "Continue 2") // Position 2 (watchpoint gone out of scope)
  5683  
  5684  		if len(p.Breakpoints().M) != clearlen+1 {
  5685  			// want 1 user breakpoint set at retaddr
  5686  			t.Errorf("wrong number of breakpoints after watchpoint goes out of scope: %d", len(p.Breakpoints().M)-clearlen)
  5687  		}
  5688  
  5689  		if len(p.Breakpoints().WatchOutOfScope) != 1 {
  5690  			t.Errorf("wrong number of out-of-scope watchpoints after watchpoint goes out of scope: %d", len(p.Breakpoints().WatchOutOfScope))
  5691  		}
  5692  
  5693  		err = p.ClearBreakpoint(retaddr)
  5694  		assertNoError(err, t, "ClearBreakpoint")
  5695  
  5696  		if len(p.Breakpoints().M) != clearlen {
  5697  			// want 1 user breakpoint set at retaddr
  5698  			t.Errorf("wrong number of breakpoints after removing user breakpoint: %d", len(p.Breakpoints().M)-clearlen)
  5699  		}
  5700  	})
  5701  }
  5702  
  5703  func TestWatchpointStackBackwardsOutOfScope(t *testing.T) {
  5704  	skipUnlessOn(t, "only for recorded targets", "rr")
  5705  	protest.AllowRecording(t)
  5706  
  5707  	withTestProcess("databpstack", t, func(p *proc.Target, fixture protest.Fixture) {
  5708  		setFileBreakpoint(p, t, fixture.Source, 11) // Position 0 breakpoint
  5709  		clearlen := len(p.Breakpoints().M)
  5710  
  5711  		assertNoError(p.Continue(), t, "Continue 0")
  5712  		assertLineNumber(p, t, 11, "Continue 0") // Position 0
  5713  
  5714  		scope, err := proc.GoroutineScope(p, p.CurrentThread())
  5715  		assertNoError(err, t, "GoroutineScope")
  5716  
  5717  		_, err = p.SetWatchpoint(0, scope, "w", proc.WatchWrite, nil)
  5718  		assertNoError(err, t, "SetDataBreakpoint(write-only)")
  5719  
  5720  		assertNoError(p.Continue(), t, "Continue 1")
  5721  		assertLineNumber(p, t, 17, "Continue 1") // Position 1
  5722  
  5723  		p.ChangeDirection(proc.Backward)
  5724  
  5725  		assertNoError(p.Continue(), t, "Continue 2")
  5726  		t.Logf("%#v", p.CurrentThread().Breakpoint().Breakpoint)
  5727  		assertLineNumber(p, t, 16, "Continue 2") // Position 1 again (because of inverted movement)
  5728  
  5729  		assertNoError(p.Continue(), t, "Continue 3")
  5730  		t.Logf("%#v", p.CurrentThread().Breakpoint().Breakpoint)
  5731  		assertLineNumber(p, t, 11, "Continue 3") // Position 0 (breakpoint 1 hit)
  5732  
  5733  		assertNoError(p.Continue(), t, "Continue 4")
  5734  		t.Logf("%#v", p.CurrentThread().Breakpoint().Breakpoint)
  5735  		assertLineNumber(p, t, 23, "Continue 4") // Position 2 (watchpoint gone out of scope)
  5736  
  5737  		if len(p.Breakpoints().M) != clearlen {
  5738  			t.Errorf("wrong number of breakpoints after watchpoint goes out of scope: %d", len(p.Breakpoints().M)-clearlen)
  5739  		}
  5740  
  5741  		if len(p.Breakpoints().WatchOutOfScope) != 1 {
  5742  			t.Errorf("wrong number of out-of-scope watchpoints after watchpoint goes out of scope: %d", len(p.Breakpoints().WatchOutOfScope))
  5743  		}
  5744  
  5745  		if len(p.Breakpoints().M) != clearlen {
  5746  			// want 1 user breakpoint set at retaddr
  5747  			t.Errorf("wrong number of breakpoints after removing user breakpoint: %d", len(p.Breakpoints().M)-clearlen)
  5748  		}
  5749  	})
  5750  }
  5751  
  5752  func TestSetOnFunctions(t *testing.T) {
  5753  	// The set command between function variables should fail with an error
  5754  	// Issue #2691
  5755  	withTestProcess("goroutinestackprog", t, func(p *proc.Target, fixture protest.Fixture) {
  5756  		setFunctionBreakpoint(p, t, "main.main")
  5757  		assertNoError(p.Continue(), t, "Continue()")
  5758  		scope, err := proc.GoroutineScope(p, p.CurrentThread())
  5759  		assertNoError(err, t, "GoroutineScope")
  5760  		err = scope.SetVariable("main.func1", "main.func2")
  5761  		if err == nil {
  5762  			t.Fatal("expected error when assigning between function variables")
  5763  		}
  5764  	})
  5765  }
  5766  
  5767  func TestSetYMMRegister(t *testing.T) {
  5768  	skipUnlessOn(t, "N/A", "darwin", "amd64")
  5769  	// Checks that setting a XMM register works. This checks that the
  5770  	// workaround for a bug in debugserver works.
  5771  	// See issue #2767.
  5772  	withTestProcess("setymmreg/", t, func(p *proc.Target, fixture protest.Fixture) {
  5773  		setFunctionBreakpoint(p, t, "main.asmFunc")
  5774  		assertNoError(p.Continue(), t, "Continue()")
  5775  
  5776  		getReg := func(pos string) *op.DwarfRegister {
  5777  			regs := getRegisters(p, t)
  5778  
  5779  			arch := p.BinInfo().Arch
  5780  			dregs := arch.RegistersToDwarfRegisters(0, regs)
  5781  
  5782  			r := dregs.Reg(regnum.AMD64_XMM0)
  5783  			t.Logf("%s: %#v", pos, r)
  5784  			return r
  5785  		}
  5786  
  5787  		getReg("before")
  5788  
  5789  		p.CurrentThread().SetReg(regnum.AMD64_XMM0, op.DwarfRegisterFromBytes([]byte{
  5790  			0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
  5791  			0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
  5792  			0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
  5793  			0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44}))
  5794  		assertNoError(p.CurrentThread().StepInstruction(), t, "SetpInstruction")
  5795  
  5796  		xmm0 := getReg("after")
  5797  
  5798  		for i := range xmm0.Bytes {
  5799  			if xmm0.Bytes[i] != 0x44 {
  5800  				t.Fatalf("wrong register value")
  5801  			}
  5802  		}
  5803  	})
  5804  }
  5805  
  5806  func TestNilPtrDerefInBreakInstr(t *testing.T) {
  5807  	// Checks that having a breakpoint on the exact instruction that causes a
  5808  	// nil pointer dereference does not cause problems.
  5809  
  5810  	var asmfile string
  5811  	switch runtime.GOARCH {
  5812  	case "amd64":
  5813  		asmfile = "main_amd64.s"
  5814  	case "arm64":
  5815  		asmfile = "main_arm64.s"
  5816  	case "386":
  5817  		asmfile = "main_386.s"
  5818  	default:
  5819  		t.Fatalf("assembly file for %s not provided", runtime.GOARCH)
  5820  	}
  5821  
  5822  	withTestProcess("asmnilptr/", t, func(p *proc.Target, fixture protest.Fixture) {
  5823  		f := filepath.Join(fixture.BuildDir, asmfile)
  5824  		f = strings.Replace(f, "\\", "/", -1)
  5825  		setFileBreakpoint(p, t, f, 5)
  5826  		t.Logf("first continue")
  5827  		assertNoError(p.Continue(), t, "Continue()")
  5828  		t.Logf("second continue")
  5829  		err := p.Continue()
  5830  		if runtime.GOOS == "darwin" && err != nil && err.Error() == "bad access" {
  5831  			// this is also ok
  5832  			return
  5833  		}
  5834  		assertNoError(err, t, "Continue()")
  5835  		bp := p.CurrentThread().Breakpoint()
  5836  		if bp != nil {
  5837  			t.Logf("%#v\n", bp.Breakpoint)
  5838  		}
  5839  		if bp == nil || (bp.Logical.Name != proc.UnrecoveredPanic) {
  5840  			t.Fatalf("no breakpoint hit or wrong breakpoint hit: %#v", bp)
  5841  		}
  5842  	})
  5843  }
  5844  
  5845  func TestStepIntoAutogeneratedSkip(t *testing.T) {
  5846  	// Tests that autogenerated functions are skipped with the new naming
  5847  	// scheme for autogenerated functions (issue #2948).
  5848  	withTestProcess("stepintobug", t, func(p *proc.Target, fixture protest.Fixture) {
  5849  		setFileBreakpoint(p, t, fixture.Source, 9)
  5850  		assertNoError(p.Continue(), t, "Continue()")
  5851  		assertNoError(p.Step(), t, "Step")
  5852  		assertLineNumber(p, t, 12, "After step")
  5853  	})
  5854  }
  5855  
  5856  func TestCallInjectionFlagCorruption(t *testing.T) {
  5857  	// debugCallV2 has a bug in amd64 where its tail corrupts the FLAGS register by running an ADD instruction.
  5858  	// Since this problem exists in many versions of Go, instead of fixing
  5859  	// debugCallV2, we work around this problem by restoring FLAGS, one extra
  5860  	// time, after stepping out of debugCallV2.
  5861  	// Fixes issue https://github.com/go-delve/delve/issues/2985
  5862  	skipUnlessOn(t, "not relevant", "amd64")
  5863  	protest.MustSupportFunctionCalls(t, testBackend)
  5864  
  5865  	withTestProcessArgs("badflags", t, ".", []string{"0"}, 0, func(p *proc.Target, fixture protest.Fixture) {
  5866  		mainfn := p.BinInfo().LookupFunc["main.main"]
  5867  
  5868  		// Find JNZ instruction on line :14
  5869  		var addr uint64
  5870  		text, err := proc.Disassemble(p.Memory(), nil, p.Breakpoints(), p.BinInfo(), mainfn.Entry, mainfn.End)
  5871  		assertNoError(err, t, "Disassemble")
  5872  		for _, instr := range text {
  5873  			if instr.Loc.Line != 14 {
  5874  				continue
  5875  			}
  5876  			if proc.IsJNZ(instr.Inst) {
  5877  				addr = instr.Loc.PC
  5878  			}
  5879  		}
  5880  		if addr == 0 {
  5881  			t.Fatalf("Could not find JNZ instruction at line :14")
  5882  		}
  5883  
  5884  		// Create breakpoint
  5885  		_, err = p.SetBreakpoint(0, addr, proc.UserBreakpoint, nil)
  5886  		assertNoError(err, t, "SetBreakpoint")
  5887  
  5888  		// Continue to breakpoint
  5889  		assertNoError(p.Continue(), t, "Continue()")
  5890  		assertLineNumber(p, t, 14, "expected line :14")
  5891  
  5892  		// Save RFLAGS register
  5893  		rflagsBeforeCall := p.BinInfo().Arch.RegistersToDwarfRegisters(0, getRegisters(p, t)).Uint64Val(regnum.AMD64_Rflags)
  5894  		t.Logf("rflags before = %#x", rflagsBeforeCall)
  5895  
  5896  		// Inject call to main.g()
  5897  		assertNoError(proc.EvalExpressionWithCalls(p, p.SelectedGoroutine(), "g()", normalLoadConfig, true), t, "Call")
  5898  
  5899  		// Check RFLAGS register after the call
  5900  		rflagsAfterCall := p.BinInfo().Arch.RegistersToDwarfRegisters(0, getRegisters(p, t)).Uint64Val(regnum.AMD64_Rflags)
  5901  		t.Logf("rflags after = %#x", rflagsAfterCall)
  5902  
  5903  		if rflagsBeforeCall != rflagsAfterCall {
  5904  			t.Errorf("mismatched rflags value")
  5905  		}
  5906  
  5907  		// Single step and check where we end up
  5908  		assertNoError(p.Step(), t, "Step()")
  5909  		assertLineNumber(p, t, 17, "expected line :17") // since we passed "0" as argument we should be going into the false branch at line :17
  5910  	})
  5911  }