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