--- /dev/null
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build cgo
+
+package pe
+
+import (
+ "os/exec"
+ "testing"
+)
+
+func testCgoDWARF(t *testing.T, linktype int) {
+ if _, err := exec.LookPath("gcc"); err != nil {
+ t.Skip("skipping test: gcc is missing")
+ }
+ testDWARF(t, linktype)
+}
+
+func TestDefaultLinkerDWARF(t *testing.T) {
+ t.Skip("skipping broken test: see issue 10776")
+ testCgoDWARF(t, linkCgoDefault)
+}
+
+func TestInternalLinkerDWARF(t *testing.T) {
+ testCgoDWARF(t, linkCgoInternal)
+}
+
+func TestExternalLinkerDWARF(t *testing.T) {
+ t.Skip("skipping broken test: see issue 10776")
+ testCgoDWARF(t, linkCgoExternal)
+}
"os/exec"
"path/filepath"
"reflect"
+ "regexp"
"runtime"
+ "strconv"
"testing"
+ "text/template"
)
type fileTest struct {
}
}
-func TestDWARF(t *testing.T) {
+const (
+ linkNoCgo = iota
+ linkCgoDefault
+ linkCgoInternal
+ linkCgoExternal
+)
+
+func testDWARF(t *testing.T, linktype int) {
if runtime.GOOS != "windows" {
t.Skip("skipping windows only test")
}
+ testenv.MustHaveGoRun(t)
tmpdir, err := ioutil.TempDir("", "TestDWARF")
if err != nil {
- t.Fatal("TempDir failed: ", err)
+ t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
- prog := `
-package main
-func main() {
-}
-`
src := filepath.Join(tmpdir, "a.go")
+ file, err := os.Create(src)
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = template.Must(template.New("main").Parse(testprog)).Execute(file, linktype != linkNoCgo)
+ if err != nil {
+ if err := file.Close(); err != nil {
+ t.Error(err)
+ }
+ t.Fatal(err)
+ }
+ if err := file.Close(); err != nil {
+ t.Fatal(err)
+ }
+
exe := filepath.Join(tmpdir, "a.exe")
- err = ioutil.WriteFile(src, []byte(prog), 0644)
- output, err := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, src).CombinedOutput()
+ args := []string{"build", "-o", exe}
+ switch linktype {
+ case linkNoCgo:
+ case linkCgoDefault:
+ case linkCgoInternal:
+ args = append(args, "-ldflags", "-linkmode=internal")
+ case linkCgoExternal:
+ args = append(args, "-ldflags", "-linkmode=external")
+ default:
+ t.Fatalf("invalid linktype parameter of %v", linktype)
+ }
+ args = append(args, src)
+ out, err := exec.Command(testenv.GoToolPath(t), args...).CombinedOutput()
if err != nil {
- t.Fatalf("building test executable failed: %s %s", err, output)
+ t.Fatalf("building test executable failed: %s %s", err, out)
+ }
+ out, err = exec.Command(exe).CombinedOutput()
+ if err != nil {
+ t.Fatalf("running test executable failed: %s %s", err, out)
+ }
+
+ matches := regexp.MustCompile("main=(.*)\n").FindStringSubmatch(string(out))
+ if len(matches) < 2 {
+ t.Fatalf("unexpected program output: %s", out)
+ }
+ wantaddr, err := strconv.ParseUint(matches[1], 0, 64)
+ if err != nil {
+ t.Fatalf("unexpected main address %q: %s", matches[1], err)
}
f, err := Open(exe)
break
}
if e.Tag == dwarf.TagSubprogram {
- for _, f := range e.Field {
- if f.Attr == dwarf.AttrName && e.Val(dwarf.AttrName) == "main.main" {
+ if name, ok := e.Val(dwarf.AttrName).(string); ok && name == "main.main" {
+ if addr, ok := e.Val(dwarf.AttrLowpc).(uint64); ok && addr == wantaddr {
return
}
}
}
}
}
+
+func TestDWARF(t *testing.T) {
+ testDWARF(t, linkNoCgo)
+}
+
+const testprog = `
+package main
+
+import "fmt"
+{{if .}}import "C"
+{{end}}
+
+func main() {
+ fmt.Printf("main=%p\n", main)
+}
+`