Source file
src/cmd/link/dwarf_test.go
1
2
3
4
5 package main
6
7 import (
8 "bytes"
9 cmddwarf "cmd/internal/dwarf"
10 "cmd/internal/objfile"
11 "cmd/internal/quoted"
12 "debug/dwarf"
13 "internal/platform"
14 "internal/testenv"
15 "os"
16 "os/exec"
17 "path"
18 "path/filepath"
19 "runtime"
20 "strings"
21 "testing"
22 )
23
24
25
26
27
28
29
30
31 func TestMain(m *testing.M) {
32
33
34
35 if os.Getenv("LINK_TEST_TOOLEXEC") != "" {
36 if strings.TrimSuffix(filepath.Base(os.Args[1]), ".exe") == "link" {
37
38
39 os.Args = os.Args[1:]
40 main()
41 os.Exit(0)
42 }
43
44 cmd := exec.Command(os.Args[1], os.Args[2:]...)
45 cmd.Stdin = os.Stdin
46 cmd.Stdout = os.Stdout
47 cmd.Stderr = os.Stderr
48 if err := cmd.Run(); err != nil {
49 os.Exit(1)
50 }
51 os.Exit(0)
52 }
53
54
55
56 if os.Getenv("LINK_TEST_EXEC_LINKER") != "" {
57 main()
58 os.Exit(0)
59 }
60
61 if testExe, err := os.Executable(); err == nil {
62
63 testLinker = testExe
64 }
65
66
67
68 os.Exit(m.Run())
69 }
70
71
72 var testLinker string
73
74 func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string) {
75 testenv.MustHaveCGO(t)
76 testenv.MustHaveGoBuild(t)
77
78 if !platform.ExecutableHasDWARF(runtime.GOOS, runtime.GOARCH) {
79 t.Skipf("skipping on %s/%s: no DWARF symbol table in executables", runtime.GOOS, runtime.GOARCH)
80 }
81
82 t.Parallel()
83
84 for _, prog := range []string{"testprog", "testprogcgo"} {
85 prog := prog
86 expectDWARF := expectDWARF
87 if runtime.GOOS == "aix" && prog == "testprogcgo" {
88 extld := os.Getenv("CC")
89 if extld == "" {
90 extld = "gcc"
91 }
92 extldArgs, err := quoted.Split(extld)
93 if err != nil {
94 t.Fatal(err)
95 }
96 expectDWARF, err = cmddwarf.IsDWARFEnabledOnAIXLd(extldArgs)
97 if err != nil {
98 t.Fatal(err)
99 }
100 }
101
102 t.Run(prog, func(t *testing.T) {
103 t.Parallel()
104
105 tmpDir := t.TempDir()
106
107 exe := filepath.Join(tmpDir, prog+".exe")
108 dir := "../../runtime/testdata/" + prog
109 cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-toolexec", os.Args[0], "-o", exe)
110 if buildmode != "" {
111 cmd.Args = append(cmd.Args, "-buildmode", buildmode)
112 }
113 cmd.Args = append(cmd.Args, dir)
114 cmd.Env = append(os.Environ(), env...)
115 cmd.Env = append(cmd.Env, "CGO_CFLAGS=")
116 cmd.Env = append(cmd.Env, "LINK_TEST_TOOLEXEC=1")
117 out, err := cmd.CombinedOutput()
118 if err != nil {
119 t.Fatalf("go build -o %v %v: %v\n%s", exe, dir, err, out)
120 }
121
122 if buildmode == "c-archive" {
123
124 ar := os.Getenv("AR")
125 if ar == "" {
126 ar = "ar"
127 }
128 cmd := testenv.Command(t, ar, "-x", exe)
129 cmd.Dir = tmpDir
130 if out, err := cmd.CombinedOutput(); err != nil {
131 t.Fatalf("%s -x %s: %v\n%s", ar, exe, err, out)
132 }
133 exe = filepath.Join(tmpDir, "go.o")
134 }
135
136 darwinSymbolTestIsTooFlaky := true
137 if runtime.GOOS == "darwin" && !darwinSymbolTestIsTooFlaky {
138 if _, err = exec.LookPath("symbols"); err == nil {
139
140 out, err = testenv.Command(t, "symbols", exe).CombinedOutput()
141 if err != nil {
142 t.Fatalf("symbols %v: %v: %s", filepath.Base(exe), err, out)
143 } else {
144 if bytes.HasPrefix(out, []byte("Unable to find file")) {
145
146 t.Fatalf("symbols %v: failed to parse file", filepath.Base(exe))
147 } else if bytes.Contains(out, []byte(", Empty]")) {
148 t.Fatalf("symbols %v: parsed as empty", filepath.Base(exe))
149 }
150 }
151 }
152 }
153
154 f, err := objfile.Open(exe)
155 if err != nil {
156 t.Fatal(err)
157 }
158 defer f.Close()
159
160 syms, err := f.Symbols()
161 if err != nil {
162 t.Fatal(err)
163 }
164
165 var addr uint64
166 for _, sym := range syms {
167 if sym.Name == "main.main" {
168 addr = sym.Addr
169 break
170 }
171 }
172 if addr == 0 {
173 t.Fatal("cannot find main.main in symbols")
174 }
175
176 d, err := f.DWARF()
177 if err != nil {
178 if expectDWARF {
179 t.Fatal(err)
180 }
181 return
182 } else {
183 if !expectDWARF {
184 t.Fatal("unexpected DWARF section")
185 }
186 }
187
188
189
190 wantFile := path.Join(prog, "main.go")
191 wantLine := 24
192 r := d.Reader()
193 entry, err := r.SeekPC(addr)
194 if err != nil {
195 t.Fatal(err)
196 }
197 lr, err := d.LineReader(entry)
198 if err != nil {
199 t.Fatal(err)
200 }
201 var line dwarf.LineEntry
202 if err := lr.SeekPC(addr, &line); err == dwarf.ErrUnknownPC {
203 t.Fatalf("did not find file:line for %#x (main.main)", addr)
204 } else if err != nil {
205 t.Fatal(err)
206 }
207 if !strings.HasSuffix(line.File.Name, wantFile) || line.Line != wantLine {
208 t.Errorf("%#x is %s:%d, want %s:%d", addr, line.File.Name, line.Line, filepath.Join("...", wantFile), wantLine)
209 }
210 })
211 }
212 }
213
214 func TestDWARF(t *testing.T) {
215 testDWARF(t, "", true)
216 if !testing.Short() {
217 if runtime.GOOS == "windows" {
218 t.Skip("skipping Windows/c-archive; see Issue 35512 for more.")
219 }
220 if !platform.BuildModeSupported(runtime.Compiler, "c-archive", runtime.GOOS, runtime.GOARCH) {
221 t.Skipf("skipping c-archive test on unsupported platform %s-%s", runtime.GOOS, runtime.GOARCH)
222 }
223 t.Run("c-archive", func(t *testing.T) {
224 testDWARF(t, "c-archive", true)
225 })
226 }
227 }
228
229 func TestDWARFiOS(t *testing.T) {
230
231
232
233 if testing.Short() {
234 t.Skip("skipping in short mode")
235 }
236 if runtime.GOARCH != "amd64" || runtime.GOOS != "darwin" {
237 t.Skip("skipping on non-darwin/amd64 platform")
238 }
239 if err := testenv.Command(t, "xcrun", "--help").Run(); err != nil {
240 t.Skipf("error running xcrun, required for iOS cross build: %v", err)
241 }
242
243
244 if output, err := testenv.Command(t, "xcodebuild", "-showsdks").CombinedOutput(); err != nil {
245 t.Skipf("error running xcodebuild, required for iOS cross build: %v", err)
246 } else if !strings.Contains(string(output), "iOS SDK") {
247 t.Skipf("iOS SDK not detected.")
248 }
249 cc := "CC=" + runtime.GOROOT() + "/misc/ios/clangwrap.sh"
250
251 t.Run("exe", func(t *testing.T) {
252 testDWARF(t, "", false, cc, "CGO_ENABLED=1", "GOOS=ios", "GOARCH=arm64")
253 })
254
255 t.Run("c-archive", func(t *testing.T) {
256 testDWARF(t, "c-archive", true, cc, "CGO_ENABLED=1", "GOOS=ios", "GOARCH=arm64")
257 })
258 }
259
View as plain text