github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/link/link_test.go (about) 1 package main 2 3 import ( 4 "bufio" 5 "bytes" 6 "debug/macho" 7 "github.com/gagliardetto/golang-go/not-internal/testenv" 8 "io/ioutil" 9 "os" 10 "os/exec" 11 "path/filepath" 12 "regexp" 13 "runtime" 14 "strings" 15 "testing" 16 ) 17 18 var AuthorPaidByTheColumnInch struct { 19 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."` 20 21 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."` 22 23 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."` 24 25 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."` 26 } 27 28 func TestLargeSymName(t *testing.T) { 29 // The compiler generates a symbol name using the string form of the 30 // type. This tests that the linker can read symbol names larger than 31 // the bufio buffer. Issue #15104. 32 _ = AuthorPaidByTheColumnInch 33 } 34 35 func TestIssue21703(t *testing.T) { 36 t.Parallel() 37 38 testenv.MustHaveGoBuild(t) 39 40 const source = ` 41 package main 42 const X = "\n!\n" 43 func main() {} 44 ` 45 46 tmpdir, err := ioutil.TempDir("", "issue21703") 47 if err != nil { 48 t.Fatalf("failed to create temp dir: %v\n", err) 49 } 50 defer os.RemoveAll(tmpdir) 51 52 err = ioutil.WriteFile(filepath.Join(tmpdir, "main.go"), []byte(source), 0666) 53 if err != nil { 54 t.Fatalf("failed to write main.go: %v\n", err) 55 } 56 57 cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "main.go") 58 cmd.Dir = tmpdir 59 out, err := cmd.CombinedOutput() 60 if err != nil { 61 t.Fatalf("failed to compile main.go: %v, output: %s\n", err, out) 62 } 63 64 cmd = exec.Command(testenv.GoToolPath(t), "tool", "link", "main.o") 65 cmd.Dir = tmpdir 66 out, err = cmd.CombinedOutput() 67 if err != nil { 68 t.Fatalf("failed to link main.o: %v, output: %s\n", err, out) 69 } 70 } 71 72 // TestIssue28429 ensures that the linker does not attempt to link 73 // sections not named *.o. Such sections may be used by a build system 74 // to, for example, save facts produced by a modular static analysis 75 // such as golang.org/x/tools/go/analysis. 76 func TestIssue28429(t *testing.T) { 77 t.Parallel() 78 79 testenv.MustHaveGoBuild(t) 80 81 tmpdir, err := ioutil.TempDir("", "issue28429-") 82 if err != nil { 83 t.Fatalf("failed to create temp dir: %v", err) 84 } 85 defer os.RemoveAll(tmpdir) 86 87 write := func(name, content string) { 88 err := ioutil.WriteFile(filepath.Join(tmpdir, name), []byte(content), 0666) 89 if err != nil { 90 t.Fatal(err) 91 } 92 } 93 94 runGo := func(args ...string) { 95 cmd := exec.Command(testenv.GoToolPath(t), args...) 96 cmd.Dir = tmpdir 97 out, err := cmd.CombinedOutput() 98 if err != nil { 99 t.Fatalf("'go %s' failed: %v, output: %s", 100 strings.Join(args, " "), err, out) 101 } 102 } 103 104 // Compile a main package. 105 write("main.go", "package main; func main() {}") 106 runGo("tool", "compile", "-p", "main", "main.go") 107 runGo("tool", "pack", "c", "main.a", "main.o") 108 109 // Add an extra section with a short, non-.o name. 110 // This simulates an alternative build system. 111 write(".facts", "this is not an object file") 112 runGo("tool", "pack", "r", "main.a", ".facts") 113 114 // Verify that the linker does not attempt 115 // to compile the extra section. 116 runGo("tool", "link", "main.a") 117 } 118 119 func TestUnresolved(t *testing.T) { 120 testenv.MustHaveGoBuild(t) 121 122 tmpdir, err := ioutil.TempDir("", "unresolved-") 123 if err != nil { 124 t.Fatalf("failed to create temp dir: %v", err) 125 } 126 defer os.RemoveAll(tmpdir) 127 128 write := func(name, content string) { 129 err := ioutil.WriteFile(filepath.Join(tmpdir, name), []byte(content), 0666) 130 if err != nil { 131 t.Fatal(err) 132 } 133 } 134 135 // Test various undefined references. Because of issue #29852, 136 // this used to give confusing error messages because the 137 // linker would find an undefined reference to "zero" created 138 // by the runtime package. 139 140 write("go.mod", "module testunresolved\n") 141 write("main.go", `package main 142 143 func main() { 144 x() 145 } 146 147 func x() 148 `) 149 write("main.s", ` 150 TEXT ·x(SB),0,$0 151 MOVD zero<>(SB), AX 152 MOVD zero(SB), AX 153 MOVD ·zero(SB), AX 154 RET 155 `) 156 cmd := exec.Command(testenv.GoToolPath(t), "build") 157 cmd.Dir = tmpdir 158 cmd.Env = append(os.Environ(), 159 "GOARCH=amd64", "GOOS=linux", "GOPATH="+filepath.Join(tmpdir, "_gopath")) 160 out, err := cmd.CombinedOutput() 161 if err == nil { 162 t.Fatalf("expected build to fail, but it succeeded") 163 } 164 out = regexp.MustCompile("(?m)^#.*\n").ReplaceAll(out, nil) 165 got := string(out) 166 want := `main.x: relocation target zero not defined 167 main.x: relocation target zero not defined 168 main.x: relocation target main.zero not defined 169 ` 170 if want != got { 171 t.Fatalf("want:\n%sgot:\n%s", want, got) 172 } 173 } 174 175 func TestBuildForTvOS(t *testing.T) { 176 testenv.MustHaveCGO(t) 177 testenv.MustHaveGoBuild(t) 178 179 // Only run this on darwin/amd64, where we can cross build for tvOS. 180 if runtime.GOARCH != "amd64" || runtime.GOOS != "darwin" { 181 t.Skip("skipping on non-darwin/amd64 platform") 182 } 183 if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" { 184 t.Skip("skipping in -short mode with $GO_BUILDER_NAME empty") 185 } 186 if err := exec.Command("xcrun", "--help").Run(); err != nil { 187 t.Skipf("error running xcrun, required for iOS cross build: %v", err) 188 } 189 190 sdkPath, err := exec.Command("xcrun", "--sdk", "appletvos", "--show-sdk-path").Output() 191 if err != nil { 192 t.Skip("failed to locate appletvos SDK, skipping") 193 } 194 CC := []string{ 195 "clang", 196 "-arch", 197 "arm64", 198 "-isysroot", strings.TrimSpace(string(sdkPath)), 199 "-mtvos-version-min=12.0", 200 "-fembed-bitcode", 201 "-framework", "CoreFoundation", 202 } 203 lib := filepath.Join("testdata", "lib.go") 204 tmpDir, err := ioutil.TempDir("", "go-link-TestBuildFortvOS") 205 if err != nil { 206 t.Fatal(err) 207 } 208 defer os.RemoveAll(tmpDir) 209 210 ar := filepath.Join(tmpDir, "lib.a") 211 cmd := exec.Command(testenv.GoToolPath(t), "build", "-buildmode=c-archive", "-o", ar, lib) 212 cmd.Env = append(os.Environ(), 213 "CGO_ENABLED=1", 214 "GOOS=darwin", 215 "GOARCH=arm64", 216 "CC="+strings.Join(CC, " "), 217 "CGO_CFLAGS=", // ensure CGO_CFLAGS does not contain any flags. Issue #35459 218 ) 219 if out, err := cmd.CombinedOutput(); err != nil { 220 t.Fatalf("%v: %v:\n%s", cmd.Args, err, out) 221 } 222 223 link := exec.Command(CC[0], CC[1:]...) 224 link.Args = append(link.Args, ar, filepath.Join("testdata", "main.m")) 225 if out, err := link.CombinedOutput(); err != nil { 226 t.Fatalf("%v: %v:\n%s", link.Args, err, out) 227 } 228 } 229 230 var testXFlagSrc = ` 231 package main 232 var X = "hello" 233 var Z = [99999]int{99998:12345} // make it large enough to be mmaped 234 func main() { println(X) } 235 ` 236 237 func TestXFlag(t *testing.T) { 238 testenv.MustHaveGoBuild(t) 239 240 tmpdir, err := ioutil.TempDir("", "TestXFlag") 241 if err != nil { 242 t.Fatal(err) 243 } 244 defer os.RemoveAll(tmpdir) 245 246 src := filepath.Join(tmpdir, "main.go") 247 err = ioutil.WriteFile(src, []byte(testXFlagSrc), 0666) 248 if err != nil { 249 t.Fatal(err) 250 } 251 252 cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-X=main.X=meow", "-o", filepath.Join(tmpdir, "main"), src) 253 if out, err := cmd.CombinedOutput(); err != nil { 254 t.Errorf("%v: %v:\n%s", cmd.Args, err, out) 255 } 256 } 257 258 var testMacOSVersionSrc = ` 259 package main 260 func main() { } 261 ` 262 263 func TestMacOSVersion(t *testing.T) { 264 testenv.MustHaveGoBuild(t) 265 266 tmpdir, err := ioutil.TempDir("", "TestMacOSVersion") 267 if err != nil { 268 t.Fatal(err) 269 } 270 defer os.RemoveAll(tmpdir) 271 272 src := filepath.Join(tmpdir, "main.go") 273 err = ioutil.WriteFile(src, []byte(testMacOSVersionSrc), 0666) 274 if err != nil { 275 t.Fatal(err) 276 } 277 278 exe := filepath.Join(tmpdir, "main") 279 cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-linkmode=internal", "-o", exe, src) 280 cmd.Env = append(os.Environ(), 281 "CGO_ENABLED=0", 282 "GOOS=darwin", 283 "GOARCH=amd64", 284 ) 285 if out, err := cmd.CombinedOutput(); err != nil { 286 t.Fatalf("%v: %v:\n%s", cmd.Args, err, out) 287 } 288 exef, err := os.Open(exe) 289 if err != nil { 290 t.Fatal(err) 291 } 292 exem, err := macho.NewFile(exef) 293 if err != nil { 294 t.Fatal(err) 295 } 296 found := false 297 const LC_VERSION_MIN_MACOSX = 0x24 298 checkMin := func(ver uint32) { 299 major, minor := (ver>>16)&0xff, (ver>>8)&0xff 300 if major != 10 || minor < 9 { 301 t.Errorf("LC_VERSION_MIN_MACOSX version %d.%d < 10.9", major, minor) 302 } 303 } 304 for _, cmd := range exem.Loads { 305 raw := cmd.Raw() 306 type_ := exem.ByteOrder.Uint32(raw) 307 if type_ != LC_VERSION_MIN_MACOSX { 308 continue 309 } 310 osVer := exem.ByteOrder.Uint32(raw[8:]) 311 checkMin(osVer) 312 sdkVer := exem.ByteOrder.Uint32(raw[12:]) 313 checkMin(sdkVer) 314 found = true 315 break 316 } 317 if !found { 318 t.Errorf("no LC_VERSION_MIN_MACOSX load command found") 319 } 320 } 321 322 const Issue34788src = ` 323 324 package blah 325 326 func Blah(i int) int { 327 a := [...]int{1, 2, 3, 4, 5, 6, 7, 8} 328 return a[i&7] 329 } 330 ` 331 332 func TestIssue34788Android386TLSSequence(t *testing.T) { 333 testenv.MustHaveGoBuild(t) 334 335 // This is a cross-compilation test, so it doesn't make 336 // sense to run it on every GOOS/GOARCH combination. Limit 337 // the test to amd64 + darwin/linux. 338 if runtime.GOARCH != "amd64" || 339 (runtime.GOOS != "darwin" && runtime.GOOS != "linux") { 340 t.Skip("skipping on non-{linux,darwin}/amd64 platform") 341 } 342 343 tmpdir, err := ioutil.TempDir("", "TestIssue34788Android386TLSSequence") 344 if err != nil { 345 t.Fatal(err) 346 } 347 defer os.RemoveAll(tmpdir) 348 349 src := filepath.Join(tmpdir, "blah.go") 350 err = ioutil.WriteFile(src, []byte(Issue34788src), 0666) 351 if err != nil { 352 t.Fatal(err) 353 } 354 355 obj := filepath.Join(tmpdir, "blah.o") 356 cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", obj, src) 357 cmd.Env = append(os.Environ(), "GOARCH=386", "GOOS=android") 358 if out, err := cmd.CombinedOutput(); err != nil { 359 if err != nil { 360 t.Fatalf("failed to compile blah.go: %v, output: %s\n", err, out) 361 } 362 } 363 364 // Run objdump on the resulting object. 365 cmd = exec.Command(testenv.GoToolPath(t), "tool", "objdump", obj) 366 out, oerr := cmd.CombinedOutput() 367 if oerr != nil { 368 t.Fatalf("failed to objdump blah.o: %v, output: %s\n", oerr, out) 369 } 370 371 // Sift through the output; we should not be seeing any R_TLS_LE relocs. 372 scanner := bufio.NewScanner(bytes.NewReader(out)) 373 for scanner.Scan() { 374 line := scanner.Text() 375 if strings.Contains(line, "R_TLS_LE") { 376 t.Errorf("objdump output contains unexpected R_TLS_LE reloc: %s", line) 377 } 378 } 379 } 380 381 const testStrictDupGoSrc = ` 382 package main 383 func f() 384 func main() { f() } 385 ` 386 387 const testStrictDupAsmSrc1 = ` 388 #include "textflag.h" 389 TEXT ·f(SB), NOSPLIT|DUPOK, $0-0 390 RET 391 ` 392 393 const testStrictDupAsmSrc2 = ` 394 #include "textflag.h" 395 TEXT ·f(SB), NOSPLIT|DUPOK, $0-0 396 JMP 0(PC) 397 ` 398 399 func TestStrictDup(t *testing.T) { 400 // Check that -strictdups flag works. 401 testenv.MustHaveGoBuild(t) 402 403 tmpdir, err := ioutil.TempDir("", "TestStrictDup") 404 if err != nil { 405 t.Fatal(err) 406 } 407 defer os.RemoveAll(tmpdir) 408 409 src := filepath.Join(tmpdir, "x.go") 410 err = ioutil.WriteFile(src, []byte(testStrictDupGoSrc), 0666) 411 if err != nil { 412 t.Fatal(err) 413 } 414 src = filepath.Join(tmpdir, "a.s") 415 err = ioutil.WriteFile(src, []byte(testStrictDupAsmSrc1), 0666) 416 if err != nil { 417 t.Fatal(err) 418 } 419 src = filepath.Join(tmpdir, "b.s") 420 err = ioutil.WriteFile(src, []byte(testStrictDupAsmSrc2), 0666) 421 if err != nil { 422 t.Fatal(err) 423 } 424 src = filepath.Join(tmpdir, "go.mod") 425 err = ioutil.WriteFile(src, []byte("module teststrictdup\n"), 0666) 426 if err != nil { 427 t.Fatal(err) 428 } 429 430 cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-strictdups=1") 431 cmd.Dir = tmpdir 432 out, err := cmd.CombinedOutput() 433 if err != nil { 434 t.Errorf("linking with -strictdups=1 failed: %v", err) 435 } 436 if !bytes.Contains(out, []byte("mismatched payload")) { 437 t.Errorf("unexpected output:\n%s", out) 438 } 439 440 cmd = exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-strictdups=2") 441 cmd.Dir = tmpdir 442 out, err = cmd.CombinedOutput() 443 if err == nil { 444 t.Errorf("linking with -strictdups=2 did not fail") 445 } 446 if !bytes.Contains(out, []byte("mismatched payload")) { 447 t.Errorf("unexpected output:\n%s", out) 448 } 449 }