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.
32 // C compiler with args (from $(go env CC) $(go env GOGCCFLAGS)).
38 var GOOS, GOARCH, GOPATH string
41 var testWork bool // If true, preserve temporary directories.
43 func TestMain(m *testing.M) {
44 flag.BoolVar(&testWork, "testwork", false, "if true, log and preserve the test's temporary working directory")
46 if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" {
47 fmt.Printf("SKIP - short mode and $GO_BUILDER_NAME not set\n")
50 if runtime.GOOS == "linux" {
51 if _, err := os.Stat("/etc/alpine-release"); err == nil {
52 fmt.Printf("SKIP - skipping failing test on alpine - go.dev/issue/19938\n")
57 log.SetFlags(log.Lshortfile)
61 func testMain(m *testing.M) int {
62 // We need a writable GOPATH in which to run the tests.
63 // Construct one in a temporary directory.
65 GOPATH, err = os.MkdirTemp("", "carchive_test")
72 defer os.RemoveAll(GOPATH)
74 os.Setenv("GOPATH", GOPATH)
76 // Copy testdata into GOPATH/src/testarchive, along with a go.mod file
77 // declaring the same path.
78 modRoot := filepath.Join(GOPATH, "src", "testcarchive")
79 if err := overlayDir(modRoot, "testdata"); err != nil {
82 if err := os.Chdir(modRoot); err != nil {
85 os.Setenv("PWD", modRoot)
86 if err := os.WriteFile("go.mod", []byte("module testcarchive\n"), 0666); err != nil {
91 GOARCH = goEnv("GOARCH")
92 bin = cmdToRun("./testp")
95 cc = []string{string(ccOut)}
97 out := goEnv("GOGCCFLAGS")
103 for i, c := range s {
104 if quote == '\000' && unicode.IsSpace(c) {
106 cc = append(cc, s[start:i])
114 if quote == '\000' && !backslash && (c == '"' || c == '\'') {
117 } else if !backslash && quote == c {
119 } else if (quote == '\000' || quote == '"') && !backslash && c == '\\' {
127 cc = append(cc, s[start:])
131 // -Wl,-bnoobjreorder is mandatory to keep the same layout
133 cc = append(cc, "-Wl,-bnoobjreorder")
136 // Linking runtime/cgo on ios requires the CoreFoundation framework because
137 // x_cgo_init uses CoreFoundation APIs to switch directory to the app root.
139 // TODO(#58225): This special case probably should not be needed.
140 // runtime/cgo is a very low-level package, and should not provide
141 // high-level behaviors like changing the current working directory at init.
142 cc = append(cc, "-framework", "CoreFoundation")
144 libbase := GOOS + "_" + GOARCH
145 if runtime.Compiler == "gccgo" {
146 libbase = "gccgo_" + libgodir + "_fPIC"
149 case "darwin", "ios":
150 if GOARCH == "arm64" {
153 case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris", "illumos":
157 libgodir = filepath.Join(GOPATH, "pkg", libbase, "testcarchive")
158 cc = append(cc, "-I", libgodir)
160 // Force reallocation (and avoid aliasing bugs) for parallel tests that append to cc.
161 cc = cc[:len(cc):len(cc)]
163 if GOOS == "windows" {
170 func goEnv(key string) string {
171 out, err := exec.Command("go", "env", key).Output()
173 if ee, ok := err.(*exec.ExitError); ok {
174 fmt.Fprintf(os.Stderr, "%s", ee.Stderr)
176 log.Panicf("go env %s failed:\n%s\n", key, err)
178 return strings.TrimSpace(string(out))
181 func cmdToRun(name string) []string {
182 execScript := "go_" + goEnv("GOOS") + "_" + goEnv("GOARCH") + "_exec"
183 executor, err := exec.LookPath(execScript)
185 return []string{name}
187 return []string{executor, name}
190 // genHeader writes a C header file for the C-exported declarations found in .go
191 // source files in dir.
193 // TODO(golang.org/issue/35715): This should be simpler.
194 func genHeader(t *testing.T, header, dir string) {
197 // The 'cgo' command generates a number of additional artifacts,
198 // but we're only interested in the header.
199 // Shunt the rest of the outputs to a temporary directory.
200 objDir, err := os.MkdirTemp(GOPATH, "_obj")
204 defer os.RemoveAll(objDir)
206 files, err := filepath.Glob(filepath.Join(dir, "*.go"))
211 cmd := exec.Command("go", "tool", "cgo",
213 "-exportheader", header)
214 cmd.Args = append(cmd.Args, files...)
216 if out, err := cmd.CombinedOutput(); err != nil {
222 func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) {
224 cmd := exec.Command(buildcmd[0], buildcmd[1:]...)
225 cmd.Env = append(cmd.Environ(), "GO111MODULE=off") // 'go install' only works in GOPATH mode
227 if out, err := cmd.CombinedOutput(); err != nil {
238 ccArgs := append(cc, "-o", exe, "main.c")
239 if GOOS == "windows" {
240 ccArgs = append(ccArgs, "main_windows.c", libgoa, "-lntdll", "-lws2_32", "-lwinmm")
242 ccArgs = append(ccArgs, "main_unix.c", libgoa)
244 if runtime.Compiler == "gccgo" {
245 ccArgs = append(ccArgs, "-lgo")
248 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
256 binArgs := append(cmdToRun(exe), "arg1", "arg2")
257 cmd = exec.Command(binArgs[0], binArgs[1:]...)
258 if runtime.Compiler == "gccgo" {
259 cmd.Env = append(cmd.Environ(), "GCCGO=1")
261 if out, err := cmd.CombinedOutput(); err != nil {
266 checkLineComments(t, libgoh)
269 var badLineRegexp = regexp.MustCompile(`(?m)^#line [0-9]+ "/.*$`)
271 // checkLineComments checks that the export header generated by
272 // -buildmode=c-archive doesn't have any absolute paths in the #line
273 // comments. We don't want those paths because they are unhelpful for
274 // the user and make the files change based on details of the location
276 func checkLineComments(t *testing.T, hdrname string) {
277 hdr, err := os.ReadFile(hdrname)
279 if !os.IsNotExist(err) {
284 if line := badLineRegexp.Find(hdr); line != nil {
285 t.Errorf("bad #line directive with absolute path in %s: %q", hdrname, line)
289 // checkArchive verifies that the created library looks OK.
290 // We just check a couple of things now, we can add more checks as needed.
291 func checkArchive(t *testing.T, arname string) {
295 case "aix", "darwin", "ios", "windows":
296 // We don't have any checks for non-ELF libraries yet.
297 if _, err := os.Stat(arname); err != nil {
298 t.Errorf("archive %s does not exist: %v", arname, err)
301 checkELFArchive(t, arname)
305 // checkELFArchive checks an ELF archive.
306 func checkELFArchive(t *testing.T, arname string) {
309 f, err := os.Open(arname)
311 t.Errorf("archive %s does not exist: %v", arname, err)
316 // TODO(iant): put these in a shared package? But where?
328 hdrlen = namelen + datelen + uidlen + gidlen + modelen + sizelen + fmaglen
341 var magbuf [len(magic)]byte
342 if _, err := io.ReadFull(f, magbuf[:]); err != nil {
343 t.Errorf("%s: archive too short", arname)
346 if string(magbuf[:]) != magic {
347 t.Errorf("%s: incorrect archive magic string %q", arname, magbuf)
350 off := int64(len(magic))
354 if _, err := f.Read(b[:]); err != nil {
358 t.Errorf("%s: error skipping alignment byte at %d: %v", arname, off, err)
363 var hdrbuf [hdrlen]byte
364 if _, err := io.ReadFull(f, hdrbuf[:]); err != nil {
368 t.Errorf("%s: error reading archive header at %d: %v", arname, off, err)
373 hdrslice := hdrbuf[:]
374 set := func(len int, ps *string) {
375 *ps = string(bytes.TrimSpace(hdrslice[:len]))
376 hdrslice = hdrslice[len:]
378 set(namelen, &hdr.name)
379 set(datelen, &hdr.date)
380 set(uidlen, &hdr.uid)
381 set(gidlen, &hdr.gid)
382 set(modelen, &hdr.mode)
383 set(sizelen, &hdr.size)
384 hdr.fmag = string(hdrslice[:fmaglen])
385 hdrslice = hdrslice[fmaglen:]
386 if len(hdrslice) != 0 {
387 t.Fatalf("internal error: len(hdrslice) == %d", len(hdrslice))
390 if hdr.fmag != fmag {
391 t.Errorf("%s: invalid fmagic value %q at %d", arname, hdr.fmag, off)
395 size, err := strconv.ParseInt(hdr.size, 10, 64)
397 t.Errorf("%s: error parsing size %q at %d: %v", arname, hdr.size, off, err)
404 case "__.SYMDEF", "/", "/SYM64/":
405 // The archive symbol map.
406 case "//", "ARFILENAMES/":
407 // The extended name table.
409 // This should be an ELF object.
410 checkELFArchiveObject(t, arname, off, io.NewSectionReader(f, off, size))
414 if _, err := f.Seek(off, io.SeekStart); err != nil {
415 t.Errorf("%s: failed to seek to %d: %v", arname, off, err)
420 // checkELFArchiveObject checks an object in an ELF archive.
421 func checkELFArchiveObject(t *testing.T, arname string, off int64, obj io.ReaderAt) {
424 ef, err := elf.NewFile(obj)
426 t.Errorf("%s: failed to open ELF file at %d: %v", arname, off, err)
431 // Verify section types.
432 for _, sec := range ef.Sections {
435 case ".text", ".data":
436 want = elf.SHT_PROGBITS
438 want = elf.SHT_NOBITS
440 want = elf.SHT_SYMTAB
442 want = elf.SHT_STRTAB
444 want = elf.SHT_INIT_ARRAY
446 want = elf.SHT_FINI_ARRAY
447 case ".preinit_array":
448 want = elf.SHT_PREINIT_ARRAY
450 if want != elf.SHT_NULL && sec.Type != want {
451 t.Errorf("%s: incorrect section type in elf file at %d for section %q: got %v want %v", arname, off, sec.Name, sec.Type, want)
456 func TestInstall(t *testing.T) {
458 defer os.RemoveAll(filepath.Join(GOPATH, "pkg"))
462 if runtime.Compiler == "gccgo" {
463 libgoa = "liblibgo.a"
466 // Generate the p.h header file.
468 // 'go install -i -buildmode=c-archive ./libgo' would do that too, but that
469 // would also attempt to install transitive standard-library dependencies to
470 // GOROOT, and we cannot assume that GOROOT is writable. (A non-root user may
471 // be running this test in a GOROOT owned by root.)
472 genHeader(t, "p.h", "./p")
474 testInstall(t, "./testp1"+exeSuffix,
475 filepath.Join(libgodir, libgoa),
476 filepath.Join(libgodir, "libgo.h"),
477 "go", "install", "-buildmode=c-archive", "./libgo")
479 // Test building libgo other than installing it.
480 // Header files are now present.
481 testInstall(t, "./testp2"+exeSuffix, "libgo.a", "libgo.h",
482 "go", "build", "-buildmode=c-archive", filepath.Join(".", "libgo", "libgo.go"))
484 testInstall(t, "./testp3"+exeSuffix, "libgo.a", "libgo.h",
485 "go", "build", "-buildmode=c-archive", "-o", "libgo.a", "./libgo")
488 func TestEarlySignalHandler(t *testing.T) {
490 case "darwin", "ios":
493 t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH)
496 t.Skip("skipping signal test on Windows")
501 os.Remove("libgo2.a")
502 os.Remove("libgo2.h")
503 os.Remove("testp" + exeSuffix)
504 os.RemoveAll(filepath.Join(GOPATH, "pkg"))
508 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2")
509 if out, err := cmd.CombinedOutput(); err != nil {
513 checkLineComments(t, "libgo2.h")
514 checkArchive(t, "libgo2.a")
516 ccArgs := append(cc, "-o", "testp"+exeSuffix, "main2.c", "libgo2.a")
517 if runtime.Compiler == "gccgo" {
518 ccArgs = append(ccArgs, "-lgo")
520 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
526 if runtime.GOOS == "darwin" {
529 cmd = exec.Command(bin[0], append(bin[1:], darwin)...)
531 if out, err := cmd.CombinedOutput(); err != nil {
537 func TestSignalForwarding(t *testing.T) {
538 checkSignalForwardingTest(t)
539 buildSignalForwardingTest(t)
541 cmd := exec.Command(bin[0], append(bin[1:], "1")...)
543 out, err := cmd.CombinedOutput()
544 t.Logf("%v\n%s", cmd.Args, out)
545 expectSignal(t, err, syscall.SIGSEGV, 0)
547 // SIGPIPE is never forwarded on darwin. See golang.org/issue/33384.
548 if runtime.GOOS != "darwin" && runtime.GOOS != "ios" {
549 // Test SIGPIPE forwarding
550 cmd = exec.Command(bin[0], append(bin[1:], "3")...)
552 out, err = cmd.CombinedOutput()
556 expectSignal(t, err, syscall.SIGPIPE, 0)
560 func TestSignalForwardingExternal(t *testing.T) {
561 if GOOS == "freebsd" || GOOS == "aix" {
562 t.Skipf("skipping on %s/%s; signal always goes to the Go runtime", GOOS, GOARCH)
563 } else if GOOS == "darwin" && GOARCH == "amd64" {
564 t.Skipf("skipping on %s/%s: runtime does not permit SI_USER SIGSEGV", GOOS, GOARCH)
566 checkSignalForwardingTest(t)
567 buildSignalForwardingTest(t)
569 // We want to send the process a signal and see if it dies.
570 // Normally the signal goes to the C thread, the Go signal
571 // handler picks it up, sees that it is running in a C thread,
572 // and the program dies. Unfortunately, occasionally the
573 // signal is delivered to a Go thread, which winds up
574 // discarding it because it was sent by another program and
575 // there is no Go handler for it. To avoid this, run the
576 // program several times in the hopes that it will eventually
579 for i := 0; i < tries; i++ {
580 err := runSignalForwardingTest(t, "2")
585 // If the signal is delivered to a C thread, as expected,
586 // the Go signal handler will disable itself and re-raise
587 // the signal, causing the program to die with SIGSEGV.
589 // It is also possible that the signal will be
590 // delivered to a Go thread, such as a GC thread.
591 // Currently when the Go runtime sees that a SIGSEGV was
592 // sent from a different program, it first tries to send
593 // the signal to the os/signal API. If nothing is looking
594 // for (or explicitly ignoring) SIGSEGV, then it crashes.
595 // Because the Go runtime is invoked via a c-archive,
596 // it treats this as GOTRACEBACK=crash, meaning that it
597 // dumps a stack trace for all goroutines, which it does
598 // by raising SIGQUIT. The effect is that we will see the
599 // program die with SIGQUIT in that case, not SIGSEGV.
600 if expectSignal(t, err, syscall.SIGSEGV, syscall.SIGQUIT) {
605 t.Errorf("program succeeded unexpectedly %d times", tries)
608 func TestSignalForwardingGo(t *testing.T) {
609 // This test fails on darwin-amd64 because of the special
610 // handling of user-generated SIGSEGV signals in fixsigcode in
611 // runtime/signal_darwin_amd64.go.
612 if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" {
613 t.Skip("not supported on darwin-amd64")
616 checkSignalForwardingTest(t)
617 buildSignalForwardingTest(t)
618 err := runSignalForwardingTest(t, "4")
620 // Occasionally the signal will be delivered to a C thread,
621 // and the program will crash with SIGSEGV.
622 expectSignal(t, err, syscall.SIGQUIT, syscall.SIGSEGV)
625 // checkSignalForwardingTest calls t.Skip if the SignalForwarding test
626 // doesn't work on this platform.
627 func checkSignalForwardingTest(t *testing.T) {
629 case "darwin", "ios":
632 t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH)
635 t.Skip("skipping signal test on Windows")
639 // buildSignalForwardingTest builds the executable used by the various
640 // signal forwarding tests.
641 func buildSignalForwardingTest(t *testing.T) {
644 os.Remove("libgo2.a")
645 os.Remove("libgo2.h")
646 os.Remove("testp" + exeSuffix)
647 os.RemoveAll(filepath.Join(GOPATH, "pkg"))
651 t.Log("go build -buildmode=c-archive -o libgo2.a ./libgo2")
652 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2")
653 out, err := cmd.CombinedOutput()
661 checkLineComments(t, "libgo2.h")
662 checkArchive(t, "libgo2.a")
664 ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a")
665 if runtime.Compiler == "gccgo" {
666 ccArgs = append(ccArgs, "-lgo")
669 out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
678 func runSignalForwardingTest(t *testing.T, arg string) error {
679 t.Logf("%v %s", bin, arg)
680 cmd := exec.Command(bin[0], append(bin[1:], arg)...)
682 var out strings.Builder
685 stderr, err := cmd.StderrPipe()
691 r := bufio.NewReader(stderr)
698 // Wait for trigger to ensure that process is started.
699 ok, err := r.ReadString('\n')
702 if err != nil || ok != "OK\n" {
703 t.Fatal("Did not receive OK signal")
706 var wg sync.WaitGroup
708 var errsb strings.Builder
714 // Give the program a chance to enter the function.
715 // If the program doesn't get there the test will still
716 // pass, although it doesn't quite test what we intended.
717 // This is fine as long as the program normally makes it.
718 time.Sleep(time.Millisecond)
720 cmd.Process.Signal(syscall.SIGSEGV)
737 // expectSignal checks that err, the exit status of a test program,
738 // shows a failure due to a specific signal or two. Returns whether we
739 // found an expected signal.
740 func expectSignal(t *testing.T, err error, sig1, sig2 syscall.Signal) bool {
743 t.Error("test program succeeded unexpectedly")
744 } else if ee, ok := err.(*exec.ExitError); !ok {
745 t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err)
746 } else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok {
747 t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys())
748 } else if !ws.Signaled() || (ws.Signal() != sig1 && ws.Signal() != sig2) {
750 t.Errorf("got %q; expected signal %q", ee, sig1)
752 t.Errorf("got %q; expected signal %q or %q", ee, sig1, sig2)
760 func TestOsSignal(t *testing.T) {
763 t.Skip("skipping signal test on Windows")
768 os.Remove("libgo3.a")
769 os.Remove("libgo3.h")
770 os.Remove("testp" + exeSuffix)
771 os.RemoveAll(filepath.Join(GOPATH, "pkg"))
775 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo3.a", "./libgo3")
776 if out, err := cmd.CombinedOutput(); err != nil {
780 checkLineComments(t, "libgo3.h")
781 checkArchive(t, "libgo3.a")
783 ccArgs := append(cc, "-o", "testp"+exeSuffix, "main3.c", "libgo3.a")
784 if runtime.Compiler == "gccgo" {
785 ccArgs = append(ccArgs, "-lgo")
787 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
792 if out, err := exec.Command(bin[0], bin[1:]...).CombinedOutput(); err != nil {
798 func TestSigaltstack(t *testing.T) {
801 t.Skip("skipping signal test on Windows")
806 os.Remove("libgo4.a")
807 os.Remove("libgo4.h")
808 os.Remove("testp" + exeSuffix)
809 os.RemoveAll(filepath.Join(GOPATH, "pkg"))
813 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo4.a", "./libgo4")
814 if out, err := cmd.CombinedOutput(); err != nil {
818 checkLineComments(t, "libgo4.h")
819 checkArchive(t, "libgo4.a")
821 ccArgs := append(cc, "-o", "testp"+exeSuffix, "main4.c", "libgo4.a")
822 if runtime.Compiler == "gccgo" {
823 ccArgs = append(ccArgs, "-lgo")
825 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
830 if out, err := exec.Command(bin[0], bin[1:]...).CombinedOutput(); err != nil {
836 const testar = `#!/usr/bin/env bash
837 while [[ $1 == -* ]] >/dev/null; do
841 echo "testar" > PWD/testar.ran
844 func TestExtar(t *testing.T) {
847 t.Skip("skipping signal test on Windows")
849 if runtime.Compiler == "gccgo" {
850 t.Skip("skipping -extar test when using gccgo")
852 if runtime.GOOS == "ios" {
853 t.Skip("shell scripts are not executable on iOS hosts")
858 os.Remove("libgo4.a")
859 os.Remove("libgo4.h")
861 os.Remove("testar.ran")
862 os.RemoveAll(filepath.Join(GOPATH, "pkg"))
867 dir, err := os.Getwd()
871 s := strings.Replace(testar, "PWD", dir, 1)
872 if err := os.WriteFile("testar", []byte(s), 0777); err != nil {
876 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-ldflags=-extar="+filepath.Join(dir, "testar"), "-o", "libgo4.a", "./libgo4")
877 if out, err := cmd.CombinedOutput(); err != nil {
881 checkLineComments(t, "libgo4.h")
883 if _, err := os.Stat("testar.ran"); err != nil {
884 if os.IsNotExist(err) {
885 t.Error("testar does not exist after go build")
887 t.Errorf("error checking testar: %v", err)
892 func TestPIE(t *testing.T) {
894 case "windows", "darwin", "ios", "plan9":
895 t.Skipf("skipping PIE test on %s", GOOS)
899 if runtime.Compiler == "gccgo" {
900 libgoa = "liblibgo.a"
905 os.Remove("testp" + exeSuffix)
907 os.RemoveAll(filepath.Join(GOPATH, "pkg"))
911 // Generate the p.h header file.
913 // 'go install -i -buildmode=c-archive ./libgo' would do that too, but that
914 // would also attempt to install transitive standard-library dependencies to
915 // GOROOT, and we cannot assume that GOROOT is writable. (A non-root user may
916 // be running this test in a GOROOT owned by root.)
917 genHeader(t, "p.h", "./p")
919 cmd := exec.Command("go", "build", "-buildmode=c-archive", "./libgo")
920 if out, err := cmd.CombinedOutput(); err != nil {
925 ccArgs := append(cc, "-fPIE", "-pie", "-o", "testp"+exeSuffix, "main.c", "main_unix.c", libgoa)
926 if runtime.Compiler == "gccgo" {
927 ccArgs = append(ccArgs, "-lgo")
929 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
934 binArgs := append(bin, "arg1", "arg2")
935 cmd = exec.Command(binArgs[0], binArgs[1:]...)
936 if runtime.Compiler == "gccgo" {
937 cmd.Env = append(os.Environ(), "GCCGO=1")
939 if out, err := cmd.CombinedOutput(); err != nil {
945 f, err := elf.Open("testp" + exeSuffix)
947 t.Fatal("elf.Open failed: ", err)
950 if hasDynTag(t, f, elf.DT_TEXTREL) {
951 t.Errorf("%s has DT_TEXTREL flag", "testp"+exeSuffix)
956 func hasDynTag(t *testing.T, f *elf.File, tag elf.DynTag) bool {
957 ds := f.SectionByType(elf.SHT_DYNAMIC)
959 t.Error("no SHT_DYNAMIC section")
964 t.Errorf("can't read SHT_DYNAMIC contents: %v", err)
971 t = elf.DynTag(f.ByteOrder.Uint32(d[:4]))
974 t = elf.DynTag(f.ByteOrder.Uint64(d[:8]))
984 func TestSIGPROF(t *testing.T) {
986 case "windows", "plan9":
987 t.Skipf("skipping SIGPROF test on %s", GOOS)
988 case "darwin", "ios":
989 t.Skipf("skipping SIGPROF test on %s; see https://golang.org/issue/19320", GOOS)
996 os.Remove("testp6" + exeSuffix)
997 os.Remove("libgo6.a")
998 os.Remove("libgo6.h")
1002 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo6.a", "./libgo6")
1003 out, err := cmd.CombinedOutput()
1004 t.Logf("%v\n%s", cmd.Args, out)
1008 checkLineComments(t, "libgo6.h")
1009 checkArchive(t, "libgo6.a")
1011 ccArgs := append(cc, "-o", "testp6"+exeSuffix, "main6.c", "libgo6.a")
1012 if runtime.Compiler == "gccgo" {
1013 ccArgs = append(ccArgs, "-lgo")
1015 out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
1016 t.Logf("%v\n%s", ccArgs, out)
1021 argv := cmdToRun("./testp6")
1022 cmd = exec.Command(argv[0], argv[1:]...)
1023 out, err = cmd.CombinedOutput()
1024 t.Logf("%v\n%s", argv, out)
1030 // TestCompileWithoutShared tests that if we compile code without the
1031 // -shared option, we can put it into an archive. When we use the go
1032 // tool with -buildmode=c-archive, it passes -shared to the compiler,
1033 // so we override that. The go tool doesn't work this way, but Bazel
1034 // will likely do it in the future. And it ought to work. This test
1035 // was added because at one time it did not work on PPC Linux.
1036 func TestCompileWithoutShared(t *testing.T) {
1037 // For simplicity, reuse the signal forwarding test.
1038 checkSignalForwardingTest(t)
1042 os.Remove("libgo2.a")
1043 os.Remove("libgo2.h")
1047 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-gcflags=-shared=false", "-o", "libgo2.a", "./libgo2")
1048 out, err := cmd.CombinedOutput()
1049 t.Logf("%v\n%s", cmd.Args, out)
1053 checkLineComments(t, "libgo2.h")
1054 checkArchive(t, "libgo2.a")
1056 exe := "./testnoshared" + exeSuffix
1058 // In some cases, -no-pie is needed here, but not accepted everywhere. First try
1059 // if -no-pie is accepted. See #22126.
1060 ccArgs := append(cc, "-o", exe, "-no-pie", "main5.c", "libgo2.a")
1061 if runtime.Compiler == "gccgo" {
1062 ccArgs = append(ccArgs, "-lgo")
1064 out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
1065 t.Logf("%v\n%s", ccArgs, out)
1067 // If -no-pie unrecognized, try -nopie if this is possibly clang
1068 if err != nil && bytes.Contains(out, []byte("unknown")) && !strings.Contains(cc[0], "gcc") {
1069 ccArgs = append(cc, "-o", exe, "-nopie", "main5.c", "libgo2.a")
1070 out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
1071 t.Logf("%v\n%s", ccArgs, out)
1074 // Don't use either -no-pie or -nopie
1075 if err != nil && bytes.Contains(out, []byte("unrecognized")) {
1076 ccArgs = append(cc, "-o", exe, "main5.c", "libgo2.a")
1077 out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
1078 t.Logf("%v\n%s", ccArgs, out)
1084 defer os.Remove(exe)
1087 binArgs := append(cmdToRun(exe), "1")
1088 out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput()
1089 t.Logf("%v\n%s", binArgs, out)
1090 expectSignal(t, err, syscall.SIGSEGV, 0)
1092 // SIGPIPE is never forwarded on darwin. See golang.org/issue/33384.
1093 if runtime.GOOS != "darwin" && runtime.GOOS != "ios" {
1094 binArgs := append(cmdToRun(exe), "3")
1095 out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput()
1096 t.Logf("%v\n%s", binArgs, out)
1097 expectSignal(t, err, syscall.SIGPIPE, 0)
1101 // Test that installing a second time recreates the header file.
1102 func TestCachedInstall(t *testing.T) {
1104 defer os.RemoveAll(filepath.Join(GOPATH, "pkg"))
1107 h := filepath.Join(libgodir, "libgo.h")
1109 buildcmd := []string{"go", "install", "-buildmode=c-archive", "./libgo"}
1111 cmd := exec.Command(buildcmd[0], buildcmd[1:]...)
1112 cmd.Env = append(cmd.Environ(), "GO111MODULE=off") // 'go install' only works in GOPATH mode
1114 if out, err := cmd.CombinedOutput(); err != nil {
1119 if _, err := os.Stat(h); err != nil {
1120 t.Errorf("libgo.h not installed: %v", err)
1123 if err := os.Remove(h); err != nil {
1127 cmd = exec.Command(buildcmd[0], buildcmd[1:]...)
1128 cmd.Env = append(cmd.Environ(), "GO111MODULE=off")
1130 if out, err := cmd.CombinedOutput(); err != nil {
1135 if _, err := os.Stat(h); err != nil {
1136 t.Errorf("libgo.h not installed in second run: %v", err)
1141 func TestManyCalls(t *testing.T) {
1146 os.Remove("testp7" + exeSuffix)
1147 os.Remove("libgo7.a")
1148 os.Remove("libgo7.h")
1152 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo7.a", "./libgo7")
1153 out, err := cmd.CombinedOutput()
1154 t.Logf("%v\n%s", cmd.Args, out)
1158 checkLineComments(t, "libgo7.h")
1159 checkArchive(t, "libgo7.a")
1161 ccArgs := append(cc, "-o", "testp7"+exeSuffix, "main7.c", "libgo7.a")
1162 if runtime.Compiler == "gccgo" {
1163 ccArgs = append(ccArgs, "-lgo")
1165 out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
1166 t.Logf("%v\n%s", ccArgs, out)
1171 argv := cmdToRun("./testp7")
1172 cmd = exec.Command(argv[0], argv[1:]...)
1173 sb := new(strings.Builder)
1176 if err := cmd.Start(); err != nil {
1180 timer := time.AfterFunc(time.Minute,
1182 t.Error("test program timed out")
1189 t.Logf("%v\n%s", cmd.Args, sb)
1196 func TestPreemption(t *testing.T) {
1197 if runtime.Compiler == "gccgo" {
1198 t.Skip("skipping asynchronous preemption test with gccgo")
1205 os.Remove("testp8" + exeSuffix)
1206 os.Remove("libgo8.a")
1207 os.Remove("libgo8.h")
1211 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo8.a", "./libgo8")
1212 out, err := cmd.CombinedOutput()
1213 t.Logf("%v\n%s", cmd.Args, out)
1217 checkLineComments(t, "libgo8.h")
1218 checkArchive(t, "libgo8.a")
1220 ccArgs := append(cc, "-o", "testp8"+exeSuffix, "main8.c", "libgo8.a")
1221 out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
1222 t.Logf("%v\n%s", ccArgs, out)
1227 argv := cmdToRun("./testp8")
1228 cmd = exec.Command(argv[0], argv[1:]...)
1229 sb := new(strings.Builder)
1232 if err := cmd.Start(); err != nil {
1236 timer := time.AfterFunc(time.Minute,
1238 t.Error("test program timed out")
1245 t.Logf("%v\n%s", cmd.Args, sb)