Source file
src/cmd/link/link_test.go
1
2
3
4
5 package main
6
7 import (
8 "bufio"
9 "bytes"
10 "cmd/internal/sys"
11 "debug/macho"
12 "internal/testenv"
13 "io/ioutil"
14 "os"
15 "os/exec"
16 "path/filepath"
17 "regexp"
18 "runtime"
19 "strings"
20 "testing"
21 )
22
23 var AuthorPaidByTheColumnInch struct {
24 fog int `text:"London. Michaelmas term lately over, and the Lord Chancellor sitting in Lincoln’s Inn Hall. Implacable November weather. As much mud in the streets as if the waters had but newly retired from the face of the earth, and it would not be wonderful to meet a Megalosaurus, forty feet long or so, waddling like an elephantine lizard up Holborn Hill. Smoke lowering down from chimney-pots, making a soft black drizzle, with flakes of soot in it as big as full-grown snowflakes—gone into mourning, one might imagine, for the death of the sun. Dogs, undistinguishable in mire. Horses, scarcely better; splashed to their very blinkers. Foot passengers, jostling one another’s umbrellas in a general infection of ill temper, and losing their foot-hold at street-corners, where tens of thousands of other foot passengers have been slipping and sliding since the day broke (if this day ever broke), adding new deposits to the crust upon crust of mud, sticking at those points tenaciously to the pavement, and accumulating at compound interest. Fog everywhere. Fog up the river, where it flows among green aits and meadows; fog down the river, where it rolls defiled among the tiers of shipping and the waterside pollutions of a great (and dirty) city. Fog on the Essex marshes, fog on the Kentish heights. Fog creeping into the cabooses of collier-brigs; fog lying out on the yards and hovering in the rigging of great ships; fog drooping on the gunwales of barges and small boats. Fog in the eyes and throats of ancient Greenwich pensioners, wheezing by the firesides of their wards; fog in the stem and bowl of the afternoon pipe of the wrathful skipper, down in his close cabin; fog cruelly pinching the toes and fingers of his shivering little ‘prentice boy on deck. Chance people on the bridges peeping over the parapets into a nether sky of fog, with fog all round them, as if they were up in a balloon and hanging in the misty clouds. Gas looming through the fog in divers places in the streets, much as the sun may, from the spongey fields, be seen to loom by husbandman and ploughboy. Most of the shops lighted two hours before their time—as the gas seems to know, for it has a haggard and unwilling look. The raw afternoon is rawest, and the dense fog is densest, and the muddy streets are muddiest near that leaden-headed old obstruction, appropriate ornament for the threshold of a leaden-headed old corporation, Temple Bar. And hard by Temple Bar, in Lincoln’s Inn Hall, at the very heart of the fog, sits the Lord High Chancellor in his High Court of Chancery."`
25
26 wind int `text:"It was grand to see how the wind awoke, and bent the trees, and drove the rain before it like a cloud of smoke; and to hear the solemn thunder, and to see the lightning; and while thinking with awe of the tremendous powers by which our little lives are encompassed, to consider how beneficent they are, and how upon the smallest flower and leaf there was already a freshness poured from all this seeming rage, which seemed to make creation new again."`
27
28 jarndyce int `text:"Jarndyce and Jarndyce drones on. This scarecrow of a suit has, over the course of time, become so complicated, that no man alive knows what it means. The parties to it understand it least; but it has been observed that no two Chancery lawyers can talk about it for five minutes, without coming to a total disagreement as to all the premises. Innumerable children have been born into the cause; innumerable young people have married into it; innumerable old people have died out of it. Scores of persons have deliriously found themselves made parties in Jarndyce and Jarndyce, without knowing how or why; whole families have inherited legendary hatreds with the suit. The little plaintiff or defendant, who was promised a new rocking-horse when Jarndyce and Jarndyce should be settled, has grown up, possessed himself of a real horse, and trotted away into the other world. Fair wards of court have faded into mothers and grandmothers; a long procession of Chancellors has come in and gone out; the legion of bills in the suit have been transformed into mere bills of mortality; there are not three Jarndyces left upon the earth perhaps, since old Tom Jarndyce in despair blew his brains out at a coffee-house in Chancery Lane; but Jarndyce and Jarndyce still drags its dreary length before the Court, perennially hopeless."`
29
30 principle int `text:"The one great principle of the English law is, to make business for itself. There is no other principle distinctly, certainly, and consistently maintained through all its narrow turnings. Viewed by this light it becomes a coherent scheme, and not the monstrous maze the laity are apt to think it. Let them but once clearly perceive that its grand principle is to make business for itself at their expense, and surely they will cease to grumble."`
31 }
32
33 func TestLargeSymName(t *testing.T) {
34
35
36
37 _ = AuthorPaidByTheColumnInch
38 }
39
40 func TestIssue21703(t *testing.T) {
41 t.Parallel()
42
43 testenv.MustHaveGoBuild(t)
44
45 const source = `
46 package main
47 const X = "\n!\n"
48 func main() {}
49 `
50
51 tmpdir := t.TempDir()
52
53 err := ioutil.WriteFile(filepath.Join(tmpdir, "main.go"), []byte(source), 0666)
54 if err != nil {
55 t.Fatalf("failed to write main.go: %v\n", err)
56 }
57
58 cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "main.go")
59 cmd.Dir = tmpdir
60 out, err := cmd.CombinedOutput()
61 if err != nil {
62 t.Fatalf("failed to compile main.go: %v, output: %s\n", err, out)
63 }
64
65 cmd = exec.Command(testenv.GoToolPath(t), "tool", "link", "main.o")
66 cmd.Dir = tmpdir
67 out, err = cmd.CombinedOutput()
68 if err != nil {
69 t.Fatalf("failed to link main.o: %v, output: %s\n", err, out)
70 }
71 }
72
73
74
75
76
77 func TestIssue28429(t *testing.T) {
78 t.Parallel()
79
80 testenv.MustHaveGoBuild(t)
81
82 tmpdir := t.TempDir()
83
84 write := func(name, content string) {
85 err := ioutil.WriteFile(filepath.Join(tmpdir, name), []byte(content), 0666)
86 if err != nil {
87 t.Fatal(err)
88 }
89 }
90
91 runGo := func(args ...string) {
92 cmd := exec.Command(testenv.GoToolPath(t), args...)
93 cmd.Dir = tmpdir
94 out, err := cmd.CombinedOutput()
95 if err != nil {
96 t.Fatalf("'go %s' failed: %v, output: %s",
97 strings.Join(args, " "), err, out)
98 }
99 }
100
101
102 write("main.go", "package main; func main() {}")
103 runGo("tool", "compile", "-p", "main", "main.go")
104 runGo("tool", "pack", "c", "main.a", "main.o")
105
106
107
108 write(".facts", "this is not an object file")
109 runGo("tool", "pack", "r", "main.a", ".facts")
110
111
112
113 runGo("tool", "link", "main.a")
114 }
115
116 func TestUnresolved(t *testing.T) {
117 testenv.MustHaveGoBuild(t)
118
119 t.Parallel()
120
121 tmpdir := t.TempDir()
122
123 write := func(name, content string) {
124 err := ioutil.WriteFile(filepath.Join(tmpdir, name), []byte(content), 0666)
125 if err != nil {
126 t.Fatal(err)
127 }
128 }
129
130
131
132
133
134
135 write("go.mod", "module testunresolved\n")
136 write("main.go", `package main
137
138 func main() {
139 x()
140 }
141
142 func x()
143 `)
144 write("main.s", `
145 TEXT ·x(SB),0,$0
146 MOVD zero<>(SB), AX
147 MOVD zero(SB), AX
148 MOVD ·zero(SB), AX
149 RET
150 `)
151 cmd := exec.Command(testenv.GoToolPath(t), "build")
152 cmd.Dir = tmpdir
153 cmd.Env = append(os.Environ(),
154 "GOARCH=amd64", "GOOS=linux", "GOPATH="+filepath.Join(tmpdir, "_gopath"))
155 out, err := cmd.CombinedOutput()
156 if err == nil {
157 t.Fatalf("expected build to fail, but it succeeded")
158 }
159 out = regexp.MustCompile("(?m)^#.*\n").ReplaceAll(out, nil)
160 got := string(out)
161 want := `main.x: relocation target zero not defined
162 main.x: relocation target zero not defined
163 main.x: relocation target main.zero not defined
164 `
165 if want != got {
166 t.Fatalf("want:\n%sgot:\n%s", want, got)
167 }
168 }
169
170 func TestIssue33979(t *testing.T) {
171 testenv.MustHaveGoBuild(t)
172 testenv.MustHaveCGO(t)
173 testenv.MustInternalLink(t)
174
175
176 switch runtime.GOARCH {
177 case "mips", "mipsle", "mips64", "mips64le":
178 t.Skipf("Skipping on %s/%s", runtime.GOOS, runtime.GOARCH)
179 }
180 if runtime.GOOS == "aix" ||
181 runtime.GOOS == "windows" && runtime.GOARCH == "arm64" {
182 t.Skipf("Skipping on %s/%s", runtime.GOOS, runtime.GOARCH)
183 }
184
185 t.Parallel()
186
187 tmpdir := t.TempDir()
188
189 write := func(name, content string) {
190 err := ioutil.WriteFile(filepath.Join(tmpdir, name), []byte(content), 0666)
191 if err != nil {
192 t.Fatal(err)
193 }
194 }
195
196 run := func(name string, args ...string) string {
197 cmd := exec.Command(name, args...)
198 cmd.Dir = tmpdir
199 out, err := cmd.CombinedOutput()
200 if err != nil {
201 t.Fatalf("'go %s' failed: %v, output: %s", strings.Join(args, " "), err, out)
202 }
203 return string(out)
204 }
205 runGo := func(args ...string) string {
206 return run(testenv.GoToolPath(t), args...)
207 }
208
209
210
211
212
213
214 write("main.go", `package main
215 func main() {
216 x()
217 }
218 func x()
219 `)
220
221 write("x.s", `
222 TEXT ·x(SB),0,$0
223 CALL foo(SB)
224 RET
225 `)
226 write("x.c", `
227 void undefined();
228
229 void foo() {
230 undefined();
231 }
232 `)
233
234 cc := strings.TrimSpace(runGo("env", "CC"))
235 cflags := strings.Fields(runGo("env", "GOGCCFLAGS"))
236
237
238 runGo("tool", "asm", "-gensymabis", "-o", "symabis", "x.s")
239 runGo("tool", "compile", "-symabis", "symabis", "-p", "main", "-o", "x1.o", "main.go")
240 runGo("tool", "asm", "-o", "x2.o", "x.s")
241 run(cc, append(cflags, "-c", "-o", "x3.o", "x.c")...)
242 runGo("tool", "pack", "c", "x.a", "x1.o", "x2.o", "x3.o")
243
244
245 cmd := exec.Command(testenv.GoToolPath(t), "tool", "link", "-linkmode=internal", "x.a")
246 cmd.Dir = tmpdir
247 out, err := cmd.CombinedOutput()
248 if err == nil {
249 t.Fatalf("expected link to fail, but it succeeded")
250 }
251 re := regexp.MustCompile(`(?m)^main\(.*text\): relocation target undefined not defined$`)
252 if !re.Match(out) {
253 t.Fatalf("got:\n%q\nwant:\n%s", out, re)
254 }
255 }
256
257 func TestBuildForTvOS(t *testing.T) {
258 testenv.MustHaveCGO(t)
259 testenv.MustHaveGoBuild(t)
260
261
262 if runtime.GOARCH != "amd64" || runtime.GOOS != "darwin" {
263 t.Skip("skipping on non-darwin/amd64 platform")
264 }
265 if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" {
266 t.Skip("skipping in -short mode with $GO_BUILDER_NAME empty")
267 }
268 if err := exec.Command("xcrun", "--help").Run(); err != nil {
269 t.Skipf("error running xcrun, required for iOS cross build: %v", err)
270 }
271
272 t.Parallel()
273
274 sdkPath, err := exec.Command("xcrun", "--sdk", "appletvos", "--show-sdk-path").Output()
275 if err != nil {
276 t.Skip("failed to locate appletvos SDK, skipping")
277 }
278 CC := []string{
279 "clang",
280 "-arch",
281 "arm64",
282 "-isysroot", strings.TrimSpace(string(sdkPath)),
283 "-mtvos-version-min=12.0",
284 "-fembed-bitcode",
285 }
286 CGO_LDFLAGS := []string{"-framework", "CoreFoundation"}
287 lib := filepath.Join("testdata", "testBuildFortvOS", "lib.go")
288 tmpDir := t.TempDir()
289
290 ar := filepath.Join(tmpDir, "lib.a")
291 cmd := exec.Command(testenv.GoToolPath(t), "build", "-buildmode=c-archive", "-o", ar, lib)
292 cmd.Env = append(os.Environ(),
293 "CGO_ENABLED=1",
294 "GOOS=ios",
295 "GOARCH=arm64",
296 "CC="+strings.Join(CC, " "),
297 "CGO_CFLAGS=",
298 "CGO_LDFLAGS="+strings.Join(CGO_LDFLAGS, " "),
299 )
300 if out, err := cmd.CombinedOutput(); err != nil {
301 t.Fatalf("%v: %v:\n%s", cmd.Args, err, out)
302 }
303
304 link := exec.Command(CC[0], CC[1:]...)
305 link.Args = append(link.Args, CGO_LDFLAGS...)
306 link.Args = append(link.Args, "-o", filepath.Join(tmpDir, "a.out"))
307 link.Args = append(link.Args, ar, filepath.Join("testdata", "testBuildFortvOS", "main.m"))
308 if out, err := link.CombinedOutput(); err != nil {
309 t.Fatalf("%v: %v:\n%s", link.Args, err, out)
310 }
311 }
312
313 var testXFlagSrc = `
314 package main
315 var X = "hello"
316 var Z = [99999]int{99998:12345} // make it large enough to be mmaped
317 func main() { println(X) }
318 `
319
320 func TestXFlag(t *testing.T) {
321 testenv.MustHaveGoBuild(t)
322
323 t.Parallel()
324
325 tmpdir := t.TempDir()
326
327 src := filepath.Join(tmpdir, "main.go")
328 err := ioutil.WriteFile(src, []byte(testXFlagSrc), 0666)
329 if err != nil {
330 t.Fatal(err)
331 }
332
333 cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-X=main.X=meow", "-o", filepath.Join(tmpdir, "main"), src)
334 if out, err := cmd.CombinedOutput(); err != nil {
335 t.Errorf("%v: %v:\n%s", cmd.Args, err, out)
336 }
337 }
338
339 var testMachOBuildVersionSrc = `
340 package main
341 func main() { }
342 `
343
344 func TestMachOBuildVersion(t *testing.T) {
345 testenv.MustHaveGoBuild(t)
346
347 t.Parallel()
348
349 tmpdir := t.TempDir()
350
351 src := filepath.Join(tmpdir, "main.go")
352 err := ioutil.WriteFile(src, []byte(testMachOBuildVersionSrc), 0666)
353 if err != nil {
354 t.Fatal(err)
355 }
356
357 exe := filepath.Join(tmpdir, "main")
358 cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-linkmode=internal", "-o", exe, src)
359 cmd.Env = append(os.Environ(),
360 "CGO_ENABLED=0",
361 "GOOS=darwin",
362 "GOARCH=amd64",
363 )
364 if out, err := cmd.CombinedOutput(); err != nil {
365 t.Fatalf("%v: %v:\n%s", cmd.Args, err, out)
366 }
367 exef, err := os.Open(exe)
368 if err != nil {
369 t.Fatal(err)
370 }
371 defer exef.Close()
372 exem, err := macho.NewFile(exef)
373 if err != nil {
374 t.Fatal(err)
375 }
376 found := false
377 const LC_BUILD_VERSION = 0x32
378 checkMin := func(ver uint32) {
379 major, minor := (ver>>16)&0xff, (ver>>8)&0xff
380 if major != 10 || minor < 9 {
381 t.Errorf("LC_BUILD_VERSION version %d.%d < 10.9", major, minor)
382 }
383 }
384 for _, cmd := range exem.Loads {
385 raw := cmd.Raw()
386 type_ := exem.ByteOrder.Uint32(raw)
387 if type_ != LC_BUILD_VERSION {
388 continue
389 }
390 osVer := exem.ByteOrder.Uint32(raw[12:])
391 checkMin(osVer)
392 sdkVer := exem.ByteOrder.Uint32(raw[16:])
393 checkMin(sdkVer)
394 found = true
395 break
396 }
397 if !found {
398 t.Errorf("no LC_BUILD_VERSION load command found")
399 }
400 }
401
402 const Issue34788src = `
403
404 package blah
405
406 func Blah(i int) int {
407 a := [...]int{1, 2, 3, 4, 5, 6, 7, 8}
408 return a[i&7]
409 }
410 `
411
412 func TestIssue34788Android386TLSSequence(t *testing.T) {
413 testenv.MustHaveGoBuild(t)
414
415
416
417
418 if runtime.GOARCH != "amd64" ||
419 (runtime.GOOS != "darwin" && runtime.GOOS != "linux") {
420 t.Skip("skipping on non-{linux,darwin}/amd64 platform")
421 }
422
423 t.Parallel()
424
425 tmpdir := t.TempDir()
426
427 src := filepath.Join(tmpdir, "blah.go")
428 err := ioutil.WriteFile(src, []byte(Issue34788src), 0666)
429 if err != nil {
430 t.Fatal(err)
431 }
432
433 obj := filepath.Join(tmpdir, "blah.o")
434 cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", obj, src)
435 cmd.Env = append(os.Environ(), "GOARCH=386", "GOOS=android")
436 if out, err := cmd.CombinedOutput(); err != nil {
437 t.Fatalf("failed to compile blah.go: %v, output: %s\n", err, out)
438 }
439
440
441 cmd = exec.Command(testenv.GoToolPath(t), "tool", "objdump", obj)
442 out, oerr := cmd.CombinedOutput()
443 if oerr != nil {
444 t.Fatalf("failed to objdump blah.o: %v, output: %s\n", oerr, out)
445 }
446
447
448 scanner := bufio.NewScanner(bytes.NewReader(out))
449 for scanner.Scan() {
450 line := scanner.Text()
451 if strings.Contains(line, "R_TLS_LE") {
452 t.Errorf("objdump output contains unexpected R_TLS_LE reloc: %s", line)
453 }
454 }
455 }
456
457 const testStrictDupGoSrc = `
458 package main
459 func f()
460 func main() { f() }
461 `
462
463 const testStrictDupAsmSrc1 = `
464 #include "textflag.h"
465 TEXT ·f(SB), NOSPLIT|DUPOK, $0-0
466 RET
467 `
468
469 const testStrictDupAsmSrc2 = `
470 #include "textflag.h"
471 TEXT ·f(SB), NOSPLIT|DUPOK, $0-0
472 JMP 0(PC)
473 `
474
475 const testStrictDupAsmSrc3 = `
476 #include "textflag.h"
477 GLOBL ·rcon(SB), RODATA|DUPOK, $64
478 `
479
480 const testStrictDupAsmSrc4 = `
481 #include "textflag.h"
482 GLOBL ·rcon(SB), RODATA|DUPOK, $32
483 `
484
485 func TestStrictDup(t *testing.T) {
486
487 testenv.MustHaveGoBuild(t)
488
489 asmfiles := []struct {
490 fname string
491 payload string
492 }{
493 {"a", testStrictDupAsmSrc1},
494 {"b", testStrictDupAsmSrc2},
495 {"c", testStrictDupAsmSrc3},
496 {"d", testStrictDupAsmSrc4},
497 }
498
499 t.Parallel()
500
501 tmpdir := t.TempDir()
502
503 src := filepath.Join(tmpdir, "x.go")
504 err := ioutil.WriteFile(src, []byte(testStrictDupGoSrc), 0666)
505 if err != nil {
506 t.Fatal(err)
507 }
508 for _, af := range asmfiles {
509 src = filepath.Join(tmpdir, af.fname+".s")
510 err = ioutil.WriteFile(src, []byte(af.payload), 0666)
511 if err != nil {
512 t.Fatal(err)
513 }
514 }
515 src = filepath.Join(tmpdir, "go.mod")
516 err = ioutil.WriteFile(src, []byte("module teststrictdup\n"), 0666)
517 if err != nil {
518 t.Fatal(err)
519 }
520
521 cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-strictdups=1")
522 cmd.Dir = tmpdir
523 out, err := cmd.CombinedOutput()
524 if err != nil {
525 t.Errorf("linking with -strictdups=1 failed: %v\n%s", err, string(out))
526 }
527 if !bytes.Contains(out, []byte("mismatched payload")) {
528 t.Errorf("unexpected output:\n%s", out)
529 }
530
531 cmd = exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-strictdups=2")
532 cmd.Dir = tmpdir
533 out, err = cmd.CombinedOutput()
534 if err == nil {
535 t.Errorf("linking with -strictdups=2 did not fail")
536 }
537
538
539 if !(bytes.Contains(out, []byte("mismatched payload: new length")) ||
540 bytes.Contains(out, []byte("mismatched payload: same length but different contents"))) ||
541 !bytes.Contains(out, []byte("mismatched payload: different sizes")) {
542 t.Errorf("unexpected output:\n%s", out)
543 }
544 }
545
546 const testFuncAlignSrc = `
547 package main
548 import (
549 "fmt"
550 )
551 func alignPc()
552 var alignPcFnAddr uintptr
553
554 func main() {
555 if alignPcFnAddr % 512 != 0 {
556 fmt.Printf("expected 512 bytes alignment, got %v\n", alignPcFnAddr)
557 } else {
558 fmt.Printf("PASS")
559 }
560 }
561 `
562
563 const testFuncAlignAsmSrc = `
564 #include "textflag.h"
565
566 TEXT ·alignPc(SB),NOSPLIT, $0-0
567 MOVD $2, R0
568 PCALIGN $512
569 MOVD $3, R1
570 RET
571
572 GLOBL ·alignPcFnAddr(SB),RODATA,$8
573 DATA ·alignPcFnAddr(SB)/8,$·alignPc(SB)
574 `
575
576
577
578 func TestFuncAlign(t *testing.T) {
579 if runtime.GOARCH != "arm64" || runtime.GOOS != "linux" {
580 t.Skip("skipping on non-linux/arm64 platform")
581 }
582 testenv.MustHaveGoBuild(t)
583
584 t.Parallel()
585
586 tmpdir := t.TempDir()
587
588 src := filepath.Join(tmpdir, "go.mod")
589 err := ioutil.WriteFile(src, []byte("module cmd/link/TestFuncAlign/falign"), 0666)
590 if err != nil {
591 t.Fatal(err)
592 }
593 src = filepath.Join(tmpdir, "falign.go")
594 err = ioutil.WriteFile(src, []byte(testFuncAlignSrc), 0666)
595 if err != nil {
596 t.Fatal(err)
597 }
598 src = filepath.Join(tmpdir, "falign.s")
599 err = ioutil.WriteFile(src, []byte(testFuncAlignAsmSrc), 0666)
600 if err != nil {
601 t.Fatal(err)
602 }
603
604
605 cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "falign")
606 cmd.Dir = tmpdir
607 out, err := cmd.CombinedOutput()
608 if err != nil {
609 t.Errorf("build failed: %v", err)
610 }
611 cmd = exec.Command(tmpdir + "/falign")
612 out, err = cmd.CombinedOutput()
613 if err != nil {
614 t.Errorf("failed to run with err %v, output: %s", err, out)
615 }
616 if string(out) != "PASS" {
617 t.Errorf("unexpected output: %s\n", out)
618 }
619 }
620
621 const testTrampSrc = `
622 package main
623 import "fmt"
624 func main() {
625 fmt.Println("hello")
626
627 defer func(){
628 if e := recover(); e == nil {
629 panic("did not panic")
630 }
631 }()
632 f1()
633 }
634
635 // Test deferreturn trampolines. See issue #39049.
636 func f1() { defer f2() }
637 func f2() { panic("XXX") }
638 `
639
640 func TestTrampoline(t *testing.T) {
641
642
643
644
645 switch runtime.GOARCH {
646 case "arm", "arm64", "ppc64", "ppc64le":
647 default:
648 t.Skipf("trampoline insertion is not implemented on %s", runtime.GOARCH)
649 }
650
651 testenv.MustHaveGoBuild(t)
652
653 t.Parallel()
654
655 tmpdir := t.TempDir()
656
657 src := filepath.Join(tmpdir, "hello.go")
658 err := ioutil.WriteFile(src, []byte(testTrampSrc), 0666)
659 if err != nil {
660 t.Fatal(err)
661 }
662 exe := filepath.Join(tmpdir, "hello.exe")
663
664 cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-debugtramp=2", "-o", exe, src)
665 out, err := cmd.CombinedOutput()
666 if err != nil {
667 t.Fatalf("build failed: %v\n%s", err, out)
668 }
669 cmd = exec.Command(exe)
670 out, err = cmd.CombinedOutput()
671 if err != nil {
672 t.Errorf("executable failed to run: %v\n%s", err, out)
673 }
674 if string(out) != "hello\n" {
675 t.Errorf("unexpected output:\n%s", out)
676 }
677 }
678
679 const testTrampCgoSrc = `
680 package main
681
682 // #include <stdio.h>
683 // void CHello() { printf("hello\n"); fflush(stdout); }
684 import "C"
685
686 func main() {
687 C.CHello()
688 }
689 `
690
691 func TestTrampolineCgo(t *testing.T) {
692
693
694
695
696 switch runtime.GOARCH {
697 case "arm", "arm64", "ppc64", "ppc64le":
698 default:
699 t.Skipf("trampoline insertion is not implemented on %s", runtime.GOARCH)
700 }
701
702 testenv.MustHaveGoBuild(t)
703 testenv.MustHaveCGO(t)
704
705 t.Parallel()
706
707 tmpdir := t.TempDir()
708
709 src := filepath.Join(tmpdir, "hello.go")
710 err := ioutil.WriteFile(src, []byte(testTrampCgoSrc), 0666)
711 if err != nil {
712 t.Fatal(err)
713 }
714 exe := filepath.Join(tmpdir, "hello.exe")
715
716 cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-debugtramp=2", "-o", exe, src)
717 out, err := cmd.CombinedOutput()
718 if err != nil {
719 t.Fatalf("build failed: %v\n%s", err, out)
720 }
721 cmd = exec.Command(exe)
722 out, err = cmd.CombinedOutput()
723 if err != nil {
724 t.Errorf("executable failed to run: %v\n%s", err, out)
725 }
726 if string(out) != "hello\n" && string(out) != "hello\r\n" {
727 t.Errorf("unexpected output:\n%s", out)
728 }
729
730
731
732 if runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || (runtime.GOARCH == "arm64" && runtime.GOOS == "windows") || !testenv.CanInternalLink() {
733 return
734 }
735 cmd = exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-debugtramp=2 -linkmode=internal", "-o", exe, src)
736 out, err = cmd.CombinedOutput()
737 if err != nil {
738 t.Fatalf("build failed: %v\n%s", err, out)
739 }
740 cmd = exec.Command(exe)
741 out, err = cmd.CombinedOutput()
742 if err != nil {
743 t.Errorf("executable failed to run: %v\n%s", err, out)
744 }
745 if string(out) != "hello\n" && string(out) != "hello\r\n" {
746 t.Errorf("unexpected output:\n%s", out)
747 }
748 }
749
750 func TestIndexMismatch(t *testing.T) {
751
752
753
754 testenv.MustHaveGoBuild(t)
755
756 t.Parallel()
757
758 tmpdir := t.TempDir()
759
760 aSrc := filepath.Join("testdata", "testIndexMismatch", "a.go")
761 bSrc := filepath.Join("testdata", "testIndexMismatch", "b.go")
762 mSrc := filepath.Join("testdata", "testIndexMismatch", "main.go")
763 aObj := filepath.Join(tmpdir, "a.o")
764 mObj := filepath.Join(tmpdir, "main.o")
765 exe := filepath.Join(tmpdir, "main.exe")
766
767
768 cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", aObj, aSrc)
769 t.Log(cmd)
770 out, err := cmd.CombinedOutput()
771 if err != nil {
772 t.Fatalf("compiling a.go failed: %v\n%s", err, out)
773 }
774 cmd = exec.Command(testenv.GoToolPath(t), "tool", "compile", "-I", tmpdir, "-o", mObj, mSrc)
775 t.Log(cmd)
776 out, err = cmd.CombinedOutput()
777 if err != nil {
778 t.Fatalf("compiling main.go failed: %v\n%s", err, out)
779 }
780 cmd = exec.Command(testenv.GoToolPath(t), "tool", "link", "-L", tmpdir, "-o", exe, mObj)
781 t.Log(cmd)
782 out, err = cmd.CombinedOutput()
783 if err != nil {
784 t.Errorf("linking failed: %v\n%s", err, out)
785 }
786
787
788
789 cmd = exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", aObj, bSrc)
790 t.Log(cmd)
791 out, err = cmd.CombinedOutput()
792 if err != nil {
793 t.Fatalf("compiling a.go failed: %v\n%s", err, out)
794 }
795 cmd = exec.Command(testenv.GoToolPath(t), "tool", "link", "-L", tmpdir, "-o", exe, mObj)
796 t.Log(cmd)
797 out, err = cmd.CombinedOutput()
798 if err == nil {
799 t.Fatalf("linking didn't fail")
800 }
801 if !bytes.Contains(out, []byte("fingerprint mismatch")) {
802 t.Errorf("did not see expected error message. out:\n%s", out)
803 }
804 }
805
806 func TestPErsrcBinutils(t *testing.T) {
807
808 testenv.MustHaveGoBuild(t)
809
810 if (runtime.GOARCH != "386" && runtime.GOARCH != "amd64") || runtime.GOOS != "windows" {
811
812 t.Skipf("this is only for windows/amd64 and windows/386")
813 }
814
815 t.Parallel()
816
817 tmpdir := t.TempDir()
818
819 pkgdir := filepath.Join("testdata", "pe-binutils")
820 exe := filepath.Join(tmpdir, "a.exe")
821 cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", exe)
822 cmd.Dir = pkgdir
823
824 out, err := cmd.CombinedOutput()
825 if err != nil {
826 t.Fatalf("building failed: %v, output:\n%s", err, out)
827 }
828
829
830 b, err := ioutil.ReadFile(exe)
831 if err != nil {
832 t.Fatalf("reading output failed: %v", err)
833 }
834 if !bytes.Contains(b, []byte("Hello Gophers!")) {
835 t.Fatalf("binary does not contain expected content")
836 }
837 }
838
839 func TestPErsrcLLVM(t *testing.T) {
840
841 testenv.MustHaveGoBuild(t)
842
843 if runtime.GOOS != "windows" {
844 t.Skipf("this is a windows-only test")
845 }
846
847 t.Parallel()
848
849 tmpdir := t.TempDir()
850
851 pkgdir := filepath.Join("testdata", "pe-llvm")
852 exe := filepath.Join(tmpdir, "a.exe")
853 cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", exe)
854 cmd.Dir = pkgdir
855
856 out, err := cmd.CombinedOutput()
857 if err != nil {
858 t.Fatalf("building failed: %v, output:\n%s", err, out)
859 }
860
861
862 b, err := ioutil.ReadFile(exe)
863 if err != nil {
864 t.Fatalf("reading output failed: %v", err)
865 }
866 if !bytes.Contains(b, []byte("resname RCDATA a.rc")) {
867 t.Fatalf("binary does not contain expected content")
868 }
869 }
870
871 func TestContentAddressableSymbols(t *testing.T) {
872
873 testenv.MustHaveGoBuild(t)
874
875 t.Parallel()
876
877 src := filepath.Join("testdata", "testHashedSyms", "p.go")
878 cmd := exec.Command(testenv.GoToolPath(t), "run", src)
879 out, err := cmd.CombinedOutput()
880 if err != nil {
881 t.Errorf("command %s failed: %v\n%s", cmd, err, out)
882 }
883 }
884
885 func TestReadOnly(t *testing.T) {
886
887 testenv.MustHaveGoBuild(t)
888
889 t.Parallel()
890
891 src := filepath.Join("testdata", "testRO", "x.go")
892 cmd := exec.Command(testenv.GoToolPath(t), "run", src)
893 out, err := cmd.CombinedOutput()
894 if err == nil {
895 t.Errorf("running test program did not fail. output:\n%s", out)
896 }
897 }
898
899 const testIssue38554Src = `
900 package main
901
902 type T [10<<20]byte
903
904 //go:noinline
905 func f() T {
906 return T{} // compiler will make a large stmp symbol, but not used.
907 }
908
909 func main() {
910 x := f()
911 println(x[1])
912 }
913 `
914
915 func TestIssue38554(t *testing.T) {
916 testenv.MustHaveGoBuild(t)
917
918 t.Parallel()
919
920 tmpdir := t.TempDir()
921
922 src := filepath.Join(tmpdir, "x.go")
923 err := ioutil.WriteFile(src, []byte(testIssue38554Src), 0666)
924 if err != nil {
925 t.Fatalf("failed to write source file: %v", err)
926 }
927 exe := filepath.Join(tmpdir, "x.exe")
928 cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, src)
929 out, err := cmd.CombinedOutput()
930 if err != nil {
931 t.Fatalf("build failed: %v\n%s", err, out)
932 }
933
934 fi, err := os.Stat(exe)
935 if err != nil {
936 t.Fatalf("failed to stat output file: %v", err)
937 }
938
939
940
941
942 const want = 5 << 20
943 if got := fi.Size(); got > want {
944 t.Errorf("binary too big: got %d, want < %d", got, want)
945 }
946 }
947
948 const testIssue42396src = `
949 package main
950
951 //go:noinline
952 //go:nosplit
953 func callee(x int) {
954 }
955
956 func main() {
957 callee(9)
958 }
959 `
960
961 func TestIssue42396(t *testing.T) {
962 testenv.MustHaveGoBuild(t)
963
964 if !sys.RaceDetectorSupported(runtime.GOOS, runtime.GOARCH) {
965 t.Skip("no race detector support")
966 }
967
968 t.Parallel()
969
970 tmpdir := t.TempDir()
971
972 src := filepath.Join(tmpdir, "main.go")
973 err := ioutil.WriteFile(src, []byte(testIssue42396src), 0666)
974 if err != nil {
975 t.Fatalf("failed to write source file: %v", err)
976 }
977 exe := filepath.Join(tmpdir, "main.exe")
978 cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags=-race", "-o", exe, src)
979 out, err := cmd.CombinedOutput()
980 if err == nil {
981 t.Fatalf("build unexpectedly succeeded")
982 }
983
984
985
986 if strings.Contains(string(out), "panic:") {
987 t.Fatalf("build should not fail with panic:\n%s", out)
988 }
989 const want = "reference to undefined builtin"
990 if !strings.Contains(string(out), want) {
991 t.Fatalf("error message incorrect: expected it to contain %q but instead got:\n%s\n", want, out)
992 }
993 }
994
995 const testLargeRelocSrc = `
996 package main
997
998 var x = [1<<25]byte{1<<23: 23, 1<<24: 24}
999
1000 var addr = [...]*byte{
1001 &x[1<<23-1],
1002 &x[1<<23],
1003 &x[1<<23+1],
1004 &x[1<<24-1],
1005 &x[1<<24],
1006 &x[1<<24+1],
1007 }
1008
1009 func main() {
1010 // check relocations in instructions
1011 check(x[1<<23-1], 0)
1012 check(x[1<<23], 23)
1013 check(x[1<<23+1], 0)
1014 check(x[1<<24-1], 0)
1015 check(x[1<<24], 24)
1016 check(x[1<<24+1], 0)
1017
1018 // check absolute address relocations in data
1019 check(*addr[0], 0)
1020 check(*addr[1], 23)
1021 check(*addr[2], 0)
1022 check(*addr[3], 0)
1023 check(*addr[4], 24)
1024 check(*addr[5], 0)
1025 }
1026
1027 func check(x, y byte) {
1028 if x != y {
1029 panic("FAIL")
1030 }
1031 }
1032 `
1033
1034 func TestLargeReloc(t *testing.T) {
1035
1036
1037
1038 testenv.MustHaveGoBuild(t)
1039 t.Parallel()
1040
1041 tmpdir := t.TempDir()
1042
1043 src := filepath.Join(tmpdir, "x.go")
1044 err := ioutil.WriteFile(src, []byte(testLargeRelocSrc), 0666)
1045 if err != nil {
1046 t.Fatalf("failed to write source file: %v", err)
1047 }
1048 cmd := exec.Command(testenv.GoToolPath(t), "run", src)
1049 out, err := cmd.CombinedOutput()
1050 if err != nil {
1051 t.Errorf("build failed: %v. output:\n%s", err, out)
1052 }
1053
1054 if testenv.HasCGO() {
1055 cmd = exec.Command(testenv.GoToolPath(t), "run", "-ldflags=-linkmode=external", src)
1056 out, err = cmd.CombinedOutput()
1057 if err != nil {
1058 t.Fatalf("build failed: %v. output:\n%s", err, out)
1059 }
1060 }
1061 }
1062
View as plain text