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.
24 func checkLldbPython(t
*testing
.T
) {
25 cmd
:= exec
.Command("lldb", "-P")
26 out
, err
:= cmd
.CombinedOutput()
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()
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()
47 t
.Skipf("DevToolsSecurity failed: %v", err
)
48 } else if !strings
.Contains(string(out
), "enabled") {
51 cmd
= exec
.Command("/usr/bin/groups")
52 out
, err
= cmd
.CombinedOutput()
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
= `
65 mapvar := make(map[string]string,5)
70 fmt.Println("hi") // line 10
75 const lldbScriptSource
= `
77 sys.path.append(sys.argv[1])
83 debugger = lldb.SBDebugger.Create()
84 debugger.SetAsync(True)
85 target = debugger.CreateTargetWithFileAndArch("a.exe", None)
87 print "Created target"
88 main_bp = target.BreakpointCreateByLocation("main.go", 10)
90 print "Created breakpoint"
91 process = target.LaunchSimple(None, None, os.getcwd())
93 print "Process launched"
94 listener = debugger.GetListener()
95 process.broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
97 event = lldb.SBEvent()
98 if listener.WaitForEvent(TIMEOUT_SECS, event):
99 if lldb.SBProcess.GetRestartedFromEvent(event):
101 state = process.GetState()
102 if state in [lldb.eStateUnloaded, lldb.eStateLaunching, lldb.eStateRunning]:
105 print "Timeout launching"
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)
114 print "Stopped at %s:%d" % (frame.line_entry.file.basename, frame.line_entry.line)
116 print "Stopped in %s" % (frame.function.name,)
117 var = frame.FindVariable('intvar')
119 print "intvar = %s" % (var.GetValue(),)
123 print "Process state", state
126 print "Failed to create target a.exe"
128 lldb.SBDebugger.Destroy(debugger)
132 const expectedLldbOutput
= `Created target
136 Stopped at main.go:10
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")
149 dir
, err
:= ioutil
.TempDir("", "go-build")
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)
158 t
.Fatalf("failed to create file: %v", err
)
161 cmd
:= exec
.Command(testenv
.GoToolPath(t
), "build", "-gcflags", "-N -l", "-o", "a.exe")
163 out
, err
:= cmd
.CombinedOutput()
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)
171 t
.Fatalf("failed to create script: %v", err
)
174 cmd
= exec
.Command("/usr/bin/python2.7", "script.py", lldbPath
)
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")
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)
198 t
.Fatalf("failed to create file: %v", err
)
201 cmd
:= exec
.Command(testenv
.GoToolPath(t
), "build", "-o", "a.exe")
203 out
, err
:= cmd
.CombinedOutput()
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")
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")
218 t
.Fatal("Missing aranges section")
220 verifyAranges(t
, f
.ByteOrder
, sect
.Open())
222 t
.Skip("Not an elf or macho binary.")
226 func verifyAranges(t
*testing
.T
, byteorder binary
.ByteOrder
, data io
.ReadSeeker
) {
228 UnitLength
uint32 // does not include the UnitLength field
235 offset
, err
:= data
.Seek(0, io
.SeekCurrent
)
237 t
.Fatalf("Seek error: %v", err
)
239 if err
= binary
.Read(data
, byteorder
, &header
); err
== io
.EOF
{
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
{
258 t
.Fatalf("Invalid terminator")