Make more use of REG_NREGS
[official-gcc.git] / libgo / go / runtime / runtime-lldb_test.go
blob98bc906666298367ba5f79737b7692714ea3e24d
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.
5 package runtime_test
7 import (
8 "debug/elf"
9 "debug/macho"
10 "encoding/binary"
11 "internal/testenv"
12 "io"
13 "io/ioutil"
14 "os"
15 "os/exec"
16 "path/filepath"
17 "runtime"
18 "strings"
19 "testing"
22 var lldbPath string
24 func checkLldbPython(t *testing.T) {
25 cmd := exec.Command("lldb", "-P")
26 out, err := cmd.CombinedOutput()
27 if err != nil {
28 t.Skipf("skipping due to issue running lldb: %v\n%s", err, out)
30 lldbPath = strings.TrimSpace(string(out))
32 cmd = exec.Command("/usr/bin/python2.7", "-c", "import sys;sys.path.append(sys.argv[1]);import lldb; print('go lldb python support')", lldbPath)
33 out, err = cmd.CombinedOutput()
35 if err != nil {
36 t.Skipf("skipping due to issue running python: %v\n%s", err, out)
38 if string(out) != "go lldb python support\n" {
39 t.Skipf("skipping due to lack of python lldb support: %s", out)
42 if runtime.GOOS == "darwin" {
43 // Try to see if we have debugging permissions.
44 cmd = exec.Command("/usr/sbin/DevToolsSecurity", "-status")
45 out, err = cmd.CombinedOutput()
46 if err != nil {
47 t.Skipf("DevToolsSecurity failed: %v", err)
48 } else if !strings.Contains(string(out), "enabled") {
49 t.Skip(string(out))
51 cmd = exec.Command("/usr/bin/groups")
52 out, err = cmd.CombinedOutput()
53 if err != nil {
54 t.Skipf("groups failed: %v", err)
55 } else if !strings.Contains(string(out), "_developer") {
56 t.Skip("Not in _developer group")
61 const lldbHelloSource = `
62 package main
63 import "fmt"
64 func main() {
65 mapvar := make(map[string]string,5)
66 mapvar["abc"] = "def"
67 mapvar["ghi"] = "jkl"
68 intvar := 42
69 ptrvar := &intvar
70 fmt.Println("hi") // line 10
71 _ = ptrvar
75 const lldbScriptSource = `
76 import sys
77 sys.path.append(sys.argv[1])
78 import lldb
79 import os
81 TIMEOUT_SECS = 5
83 debugger = lldb.SBDebugger.Create()
84 debugger.SetAsync(True)
85 target = debugger.CreateTargetWithFileAndArch("a.exe", None)
86 if target:
87 print "Created target"
88 main_bp = target.BreakpointCreateByLocation("main.go", 10)
89 if main_bp:
90 print "Created breakpoint"
91 process = target.LaunchSimple(None, None, os.getcwd())
92 if process:
93 print "Process launched"
94 listener = debugger.GetListener()
95 process.broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
96 while True:
97 event = lldb.SBEvent()
98 if listener.WaitForEvent(TIMEOUT_SECS, event):
99 if lldb.SBProcess.GetRestartedFromEvent(event):
100 continue
101 state = process.GetState()
102 if state in [lldb.eStateUnloaded, lldb.eStateLaunching, lldb.eStateRunning]:
103 continue
104 else:
105 print "Timeout launching"
106 break
107 if state == lldb.eStateStopped:
108 for t in process.threads:
109 if t.GetStopReason() == lldb.eStopReasonBreakpoint:
110 print "Hit breakpoint"
111 frame = t.GetFrameAtIndex(0)
112 if frame:
113 if frame.line_entry:
114 print "Stopped at %s:%d" % (frame.line_entry.file.basename, frame.line_entry.line)
115 if frame.function:
116 print "Stopped in %s" % (frame.function.name,)
117 var = frame.FindVariable('intvar')
118 if var:
119 print "intvar = %s" % (var.GetValue(),)
120 else:
121 print "no intvar"
122 else:
123 print "Process state", state
124 process.Destroy()
125 else:
126 print "Failed to create target a.exe"
128 lldb.SBDebugger.Destroy(debugger)
129 sys.exit()
132 const expectedLldbOutput = `Created target
133 Created breakpoint
134 Process launched
135 Hit breakpoint
136 Stopped at main.go:10
137 Stopped in main.main
138 intvar = 42
141 func TestLldbPython(t *testing.T) {
142 testenv.MustHaveGoBuild(t)
143 if final := os.Getenv("GOROOT_FINAL"); final != "" && runtime.GOROOT() != final {
144 t.Skip("gdb test can fail with GOROOT_FINAL pending")
147 checkLldbPython(t)
149 dir, err := ioutil.TempDir("", "go-build")
150 if err != nil {
151 t.Fatalf("failed to create temp directory: %v", err)
153 defer os.RemoveAll(dir)
155 src := filepath.Join(dir, "main.go")
156 err = ioutil.WriteFile(src, []byte(lldbHelloSource), 0644)
157 if err != nil {
158 t.Fatalf("failed to create file: %v", err)
161 cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags", "-N -l", "-o", "a.exe")
162 cmd.Dir = dir
163 out, err := cmd.CombinedOutput()
164 if err != nil {
165 t.Fatalf("building source %v\n%s", err, out)
168 src = filepath.Join(dir, "script.py")
169 err = ioutil.WriteFile(src, []byte(lldbScriptSource), 0755)
170 if err != nil {
171 t.Fatalf("failed to create script: %v", err)
174 cmd = exec.Command("/usr/bin/python2.7", "script.py", lldbPath)
175 cmd.Dir = dir
176 got, _ := cmd.CombinedOutput()
178 if string(got) != expectedLldbOutput {
179 if strings.Contains(string(got), "Timeout launching") {
180 t.Skip("Timeout launching")
182 t.Fatalf("Unexpected lldb output:\n%s", got)
186 // Check that aranges are valid even when lldb isn't installed.
187 func TestDwarfAranges(t *testing.T) {
188 testenv.MustHaveGoBuild(t)
189 dir, err := ioutil.TempDir("", "go-build")
190 if err != nil {
191 t.Fatalf("failed to create temp directory: %v", err)
193 defer os.RemoveAll(dir)
195 src := filepath.Join(dir, "main.go")
196 err = ioutil.WriteFile(src, []byte(lldbHelloSource), 0644)
197 if err != nil {
198 t.Fatalf("failed to create file: %v", err)
201 cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "a.exe")
202 cmd.Dir = dir
203 out, err := cmd.CombinedOutput()
204 if err != nil {
205 t.Fatalf("building source %v\n%s", err, out)
208 filename := filepath.Join(dir, "a.exe")
209 if f, err := elf.Open(filename); err == nil {
210 sect := f.Section(".debug_aranges")
211 if sect == nil {
212 t.Fatal("Missing aranges section")
214 verifyAranges(t, f.ByteOrder, sect.Open())
215 } else if f, err := macho.Open(filename); err == nil {
216 sect := f.Section("__debug_aranges")
217 if sect == nil {
218 t.Fatal("Missing aranges section")
220 verifyAranges(t, f.ByteOrder, sect.Open())
221 } else {
222 t.Skip("Not an elf or macho binary.")
226 func verifyAranges(t *testing.T, byteorder binary.ByteOrder, data io.ReadSeeker) {
227 var header struct {
228 UnitLength uint32 // does not include the UnitLength field
229 Version uint16
230 Offset uint32
231 AddressSize uint8
232 SegmentSize uint8
234 for {
235 offset, err := data.Seek(0, io.SeekCurrent)
236 if err != nil {
237 t.Fatalf("Seek error: %v", err)
239 if err = binary.Read(data, byteorder, &header); err == io.EOF {
240 return
241 } else if err != nil {
242 t.Fatalf("Error reading arange header: %v", err)
244 tupleSize := int64(header.SegmentSize) + 2*int64(header.AddressSize)
245 lastTupleOffset := offset + int64(header.UnitLength) + 4 - tupleSize
246 if lastTupleOffset%tupleSize != 0 {
247 t.Fatalf("Invalid arange length %d, (addr %d, seg %d)", header.UnitLength, header.AddressSize, header.SegmentSize)
249 if _, err = data.Seek(lastTupleOffset, io.SeekStart); err != nil {
250 t.Fatalf("Seek error: %v", err)
252 buf := make([]byte, tupleSize)
253 if n, err := data.Read(buf); err != nil || int64(n) < tupleSize {
254 t.Fatalf("Read error: %v", err)
256 for _, val := range buf {
257 if val != 0 {
258 t.Fatalf("Invalid terminator")