...

Source file src/runtime/runtime-lldb_test.go

Documentation: runtime

		 1  // Copyright 2016 The Go Authors. All rights reserved.
		 2  // Use of this source code is governed by a BSD-style
		 3  // license that can be found in the LICENSE file.
		 4  
		 5  package runtime_test
		 6  
		 7  import (
		 8  	"internal/testenv"
		 9  	"os"
		10  	"os/exec"
		11  	"path/filepath"
		12  	"runtime"
		13  	"strings"
		14  	"testing"
		15  )
		16  
		17  var lldbPath string
		18  
		19  func checkLldbPython(t *testing.T) {
		20  	cmd := exec.Command("lldb", "-P")
		21  	out, err := cmd.CombinedOutput()
		22  	if err != nil {
		23  		t.Skipf("skipping due to issue running lldb: %v\n%s", err, out)
		24  	}
		25  	lldbPath = strings.TrimSpace(string(out))
		26  
		27  	cmd = exec.Command("/usr/bin/python2.7", "-c", "import sys;sys.path.append(sys.argv[1]);import lldb; print('go lldb python support')", lldbPath)
		28  	out, err = cmd.CombinedOutput()
		29  
		30  	if err != nil {
		31  		t.Skipf("skipping due to issue running python: %v\n%s", err, out)
		32  	}
		33  	if string(out) != "go lldb python support\n" {
		34  		t.Skipf("skipping due to lack of python lldb support: %s", out)
		35  	}
		36  
		37  	if runtime.GOOS == "darwin" {
		38  		// Try to see if we have debugging permissions.
		39  		cmd = exec.Command("/usr/sbin/DevToolsSecurity", "-status")
		40  		out, err = cmd.CombinedOutput()
		41  		if err != nil {
		42  			t.Skipf("DevToolsSecurity failed: %v", err)
		43  		} else if !strings.Contains(string(out), "enabled") {
		44  			t.Skip(string(out))
		45  		}
		46  		cmd = exec.Command("/usr/bin/groups")
		47  		out, err = cmd.CombinedOutput()
		48  		if err != nil {
		49  			t.Skipf("groups failed: %v", err)
		50  		} else if !strings.Contains(string(out), "_developer") {
		51  			t.Skip("Not in _developer group")
		52  		}
		53  	}
		54  }
		55  
		56  const lldbHelloSource = `
		57  package main
		58  import "fmt"
		59  func main() {
		60  	mapvar := make(map[string]string,5)
		61  	mapvar["abc"] = "def"
		62  	mapvar["ghi"] = "jkl"
		63  	intvar := 42
		64  	ptrvar := &intvar
		65  	fmt.Println("hi") // line 10
		66  	_ = ptrvar
		67  }
		68  `
		69  
		70  const lldbScriptSource = `
		71  import sys
		72  sys.path.append(sys.argv[1])
		73  import lldb
		74  import os
		75  
		76  TIMEOUT_SECS = 5
		77  
		78  debugger = lldb.SBDebugger.Create()
		79  debugger.SetAsync(True)
		80  target = debugger.CreateTargetWithFileAndArch("a.exe", None)
		81  if target:
		82  	print "Created target"
		83  	main_bp = target.BreakpointCreateByLocation("main.go", 10)
		84  	if main_bp:
		85  		print "Created breakpoint"
		86  	process = target.LaunchSimple(None, None, os.getcwd())
		87  	if process:
		88  		print "Process launched"
		89  		listener = debugger.GetListener()
		90  		process.broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
		91  		while True:
		92  			event = lldb.SBEvent()
		93  			if listener.WaitForEvent(TIMEOUT_SECS, event):
		94  				if lldb.SBProcess.GetRestartedFromEvent(event):
		95  					continue
		96  				state = process.GetState()
		97  				if state in [lldb.eStateUnloaded, lldb.eStateLaunching, lldb.eStateRunning]:
		98  					continue
		99  			else:
	 100  				print "Timeout launching"
	 101  			break
	 102  		if state == lldb.eStateStopped:
	 103  			for t in process.threads:
	 104  				if t.GetStopReason() == lldb.eStopReasonBreakpoint:
	 105  					print "Hit breakpoint"
	 106  					frame = t.GetFrameAtIndex(0)
	 107  					if frame:
	 108  						if frame.line_entry:
	 109  							print "Stopped at %s:%d" % (frame.line_entry.file.basename, frame.line_entry.line)
	 110  						if frame.function:
	 111  							print "Stopped in %s" % (frame.function.name,)
	 112  						var = frame.FindVariable('intvar')
	 113  						if var:
	 114  							print "intvar = %s" % (var.GetValue(),)
	 115  						else:
	 116  							print "no intvar"
	 117  		else:
	 118  			print "Process state", state
	 119  		process.Destroy()
	 120  else:
	 121  	print "Failed to create target a.exe"
	 122  
	 123  lldb.SBDebugger.Destroy(debugger)
	 124  sys.exit()
	 125  `
	 126  
	 127  const expectedLldbOutput = `Created target
	 128  Created breakpoint
	 129  Process launched
	 130  Hit breakpoint
	 131  Stopped at main.go:10
	 132  Stopped in main.main
	 133  intvar = 42
	 134  `
	 135  
	 136  func TestLldbPython(t *testing.T) {
	 137  	testenv.MustHaveGoBuild(t)
	 138  	if final := os.Getenv("GOROOT_FINAL"); final != "" && runtime.GOROOT() != final {
	 139  		t.Skip("gdb test can fail with GOROOT_FINAL pending")
	 140  	}
	 141  	testenv.SkipFlaky(t, 31188)
	 142  
	 143  	checkLldbPython(t)
	 144  
	 145  	dir := t.TempDir()
	 146  
	 147  	src := filepath.Join(dir, "main.go")
	 148  	err := os.WriteFile(src, []byte(lldbHelloSource), 0644)
	 149  	if err != nil {
	 150  		t.Fatalf("failed to create src file: %v", err)
	 151  	}
	 152  
	 153  	mod := filepath.Join(dir, "go.mod")
	 154  	err = os.WriteFile(mod, []byte("module lldbtest"), 0644)
	 155  	if err != nil {
	 156  		t.Fatalf("failed to create mod file: %v", err)
	 157  	}
	 158  
	 159  	// As of 2018-07-17, lldb doesn't support compressed DWARF, so
	 160  	// disable it for this test.
	 161  	cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags=all=-N -l", "-ldflags=-compressdwarf=false", "-o", "a.exe")
	 162  	cmd.Dir = dir
	 163  	cmd.Env = append(os.Environ(), "GOPATH=") // issue 31100
	 164  	out, err := cmd.CombinedOutput()
	 165  	if err != nil {
	 166  		t.Fatalf("building source %v\n%s", err, out)
	 167  	}
	 168  
	 169  	src = filepath.Join(dir, "script.py")
	 170  	err = os.WriteFile(src, []byte(lldbScriptSource), 0755)
	 171  	if err != nil {
	 172  		t.Fatalf("failed to create script: %v", err)
	 173  	}
	 174  
	 175  	cmd = exec.Command("/usr/bin/python2.7", "script.py", lldbPath)
	 176  	cmd.Dir = dir
	 177  	got, _ := cmd.CombinedOutput()
	 178  
	 179  	if string(got) != expectedLldbOutput {
	 180  		if strings.Contains(string(got), "Timeout launching") {
	 181  			t.Skip("Timeout launching")
	 182  		}
	 183  		t.Fatalf("Unexpected lldb output:\n%s", got)
	 184  	}
	 185  }
	 186  

View as plain text