libgo: add misc/cgo files
authorIan Lance Taylor <ian@gcc.gnu.org>
Tue, 27 Jun 2017 04:21:40 +0000 (04:21 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 27 Jun 2017 04:21:40 +0000 (04:21 +0000)
    Copy all the misc/cgo files from the gc toolchain into libgo/misc.

    These will be used for testing purposes by later changes to the
    gotools directory.

    Reviewed-on: https://go-review.googlesource.com/46721

From-SVN: r249674

270 files changed:
gcc/go/gofrontend/MERGE
libgo/merge.sh
libgo/misc/cgo/errors/err1.go [new file with mode: 0644]
libgo/misc/cgo/errors/err2.go [new file with mode: 0644]
libgo/misc/cgo/errors/err3.go [new file with mode: 0644]
libgo/misc/cgo/errors/issue11097a.go [new file with mode: 0644]
libgo/misc/cgo/errors/issue11097b.go [new file with mode: 0644]
libgo/misc/cgo/errors/issue13129.go [new file with mode: 0644]
libgo/misc/cgo/errors/issue13423.go [new file with mode: 0644]
libgo/misc/cgo/errors/issue13635.go [new file with mode: 0644]
libgo/misc/cgo/errors/issue13830.go [new file with mode: 0644]
libgo/misc/cgo/errors/issue14669.go [new file with mode: 0644]
libgo/misc/cgo/errors/issue16116.go [new file with mode: 0644]
libgo/misc/cgo/errors/issue16591.go [new file with mode: 0644]
libgo/misc/cgo/errors/issue7757.go [new file with mode: 0644]
libgo/misc/cgo/errors/issue8442.go [new file with mode: 0644]
libgo/misc/cgo/errors/malloc.go [new file with mode: 0644]
libgo/misc/cgo/errors/ptr.go [new file with mode: 0644]
libgo/misc/cgo/errors/test.bash [new file with mode: 0644]
libgo/misc/cgo/fortran/answer.f90 [new file with mode: 0644]
libgo/misc/cgo/fortran/fortran.go [new file with mode: 0644]
libgo/misc/cgo/fortran/fortran_test.go [new file with mode: 0644]
libgo/misc/cgo/fortran/helloworld/helloworld.f90 [new file with mode: 0644]
libgo/misc/cgo/fortran/test.bash [new file with mode: 0644]
libgo/misc/cgo/gmp/fib.go [new file with mode: 0644]
libgo/misc/cgo/gmp/gmp.go [new file with mode: 0644]
libgo/misc/cgo/gmp/pi.go [new file with mode: 0644]
libgo/misc/cgo/life/c-life.c [new file with mode: 0644]
libgo/misc/cgo/life/life.go [new file with mode: 0644]
libgo/misc/cgo/life/life.h [new file with mode: 0644]
libgo/misc/cgo/life/main.go [new file with mode: 0644]
libgo/misc/cgo/life/main.out [new file with mode: 0644]
libgo/misc/cgo/nocgo/nocgo.go [new file with mode: 0644]
libgo/misc/cgo/nocgo/nocgo_test.go [new file with mode: 0644]
libgo/misc/cgo/stdio/chain.go [new file with mode: 0644]
libgo/misc/cgo/stdio/chain.out [new file with mode: 0644]
libgo/misc/cgo/stdio/fib.go [new file with mode: 0644]
libgo/misc/cgo/stdio/fib.out [new file with mode: 0644]
libgo/misc/cgo/stdio/file.go [new file with mode: 0644]
libgo/misc/cgo/stdio/hello.go [new file with mode: 0644]
libgo/misc/cgo/stdio/hello.out [new file with mode: 0644]
libgo/misc/cgo/stdio/run.out [new file with mode: 0644]
libgo/misc/cgo/stdio/stdio.go [new file with mode: 0644]
libgo/misc/cgo/test/align.go [new file with mode: 0644]
libgo/misc/cgo/test/api.go [new file with mode: 0644]
libgo/misc/cgo/test/backdoor.go [new file with mode: 0644]
libgo/misc/cgo/test/basic.go [new file with mode: 0644]
libgo/misc/cgo/test/buildid_linux.go [new file with mode: 0644]
libgo/misc/cgo/test/callback.go [new file with mode: 0644]
libgo/misc/cgo/test/callback_c.c [new file with mode: 0644]
libgo/misc/cgo/test/callback_c_gc.c [new file with mode: 0644]
libgo/misc/cgo/test/callback_c_gccgo.c [new file with mode: 0644]
libgo/misc/cgo/test/cflags.go [new file with mode: 0644]
libgo/misc/cgo/test/cgo_linux_test.go [new file with mode: 0644]
libgo/misc/cgo/test/cgo_stubs_android_test.go [new file with mode: 0644]
libgo/misc/cgo/test/cgo_test.go [new file with mode: 0644]
libgo/misc/cgo/test/cgo_thread_lock.go [new file with mode: 0644]
libgo/misc/cgo/test/cgo_unix_test.go [new file with mode: 0644]
libgo/misc/cgo/test/checkconst.go [new file with mode: 0644]
libgo/misc/cgo/test/complex.go [new file with mode: 0644]
libgo/misc/cgo/test/cthread.go [new file with mode: 0644]
libgo/misc/cgo/test/cthread_unix.c [new file with mode: 0644]
libgo/misc/cgo/test/cthread_windows.c [new file with mode: 0644]
libgo/misc/cgo/test/duplicate_symbol.go [new file with mode: 0644]
libgo/misc/cgo/test/env.go [new file with mode: 0644]
libgo/misc/cgo/test/exports.go [new file with mode: 0644]
libgo/misc/cgo/test/fpvar.go [new file with mode: 0644]
libgo/misc/cgo/test/gcc68255.go [new file with mode: 0644]
libgo/misc/cgo/test/gcc68255/a.go [new file with mode: 0644]
libgo/misc/cgo/test/gcc68255/c.c [new file with mode: 0644]
libgo/misc/cgo/test/gcc68255/c.h [new file with mode: 0644]
libgo/misc/cgo/test/helpers.go [new file with mode: 0644]
libgo/misc/cgo/test/issue10303.go [new file with mode: 0644]
libgo/misc/cgo/test/issue11925.go [new file with mode: 0644]
libgo/misc/cgo/test/issue12030.go [new file with mode: 0644]
libgo/misc/cgo/test/issue1222.go [new file with mode: 0644]
libgo/misc/cgo/test/issue1328.go [new file with mode: 0644]
libgo/misc/cgo/test/issue13402.go [new file with mode: 0644]
libgo/misc/cgo/test/issue13930.go [new file with mode: 0644]
libgo/misc/cgo/test/issue14838.go [new file with mode: 0644]
libgo/misc/cgo/test/issue1560.go [new file with mode: 0644]
libgo/misc/cgo/test/issue1635.go [new file with mode: 0644]
libgo/misc/cgo/test/issue17065.go [new file with mode: 0644]
libgo/misc/cgo/test/issue17537.go [new file with mode: 0644]
libgo/misc/cgo/test/issue18126.go [new file with mode: 0644]
libgo/misc/cgo/test/issue18146.go [new file with mode: 0644]
libgo/misc/cgo/test/issue2462.go [new file with mode: 0644]
libgo/misc/cgo/test/issue3250.go [new file with mode: 0644]
libgo/misc/cgo/test/issue3250w.go [new file with mode: 0644]
libgo/misc/cgo/test/issue3261.go [new file with mode: 0644]
libgo/misc/cgo/test/issue3729.go [new file with mode: 0644]
libgo/misc/cgo/test/issue3729w.go [new file with mode: 0644]
libgo/misc/cgo/test/issue3741.go [new file with mode: 0644]
libgo/misc/cgo/test/issue3775.go [new file with mode: 0644]
libgo/misc/cgo/test/issue3945.go [new file with mode: 0644]
libgo/misc/cgo/test/issue4029.c [new file with mode: 0644]
libgo/misc/cgo/test/issue4029.go [new file with mode: 0644]
libgo/misc/cgo/test/issue4029w.go [new file with mode: 0644]
libgo/misc/cgo/test/issue4054a.go [new file with mode: 0644]
libgo/misc/cgo/test/issue4054b.go [new file with mode: 0644]
libgo/misc/cgo/test/issue4273.c [new file with mode: 0644]
libgo/misc/cgo/test/issue4273b.c [new file with mode: 0644]
libgo/misc/cgo/test/issue4339.c [new file with mode: 0644]
libgo/misc/cgo/test/issue4339.go [new file with mode: 0644]
libgo/misc/cgo/test/issue4339.h [new file with mode: 0644]
libgo/misc/cgo/test/issue4417.go [new file with mode: 0644]
libgo/misc/cgo/test/issue4857.go [new file with mode: 0644]
libgo/misc/cgo/test/issue5227.go [new file with mode: 0644]
libgo/misc/cgo/test/issue5242.go [new file with mode: 0644]
libgo/misc/cgo/test/issue5337.go [new file with mode: 0644]
libgo/misc/cgo/test/issue5337w.go [new file with mode: 0644]
libgo/misc/cgo/test/issue5548.go [new file with mode: 0644]
libgo/misc/cgo/test/issue5548_c.c [new file with mode: 0644]
libgo/misc/cgo/test/issue5603.go [new file with mode: 0644]
libgo/misc/cgo/test/issue5740.go [new file with mode: 0644]
libgo/misc/cgo/test/issue5740a.c [new file with mode: 0644]
libgo/misc/cgo/test/issue5740b.c [new file with mode: 0644]
libgo/misc/cgo/test/issue5986.go [new file with mode: 0644]
libgo/misc/cgo/test/issue6128.go [new file with mode: 0644]
libgo/misc/cgo/test/issue6390.go [new file with mode: 0644]
libgo/misc/cgo/test/issue6472.go [new file with mode: 0644]
libgo/misc/cgo/test/issue6506.go [new file with mode: 0644]
libgo/misc/cgo/test/issue6612.go [new file with mode: 0644]
libgo/misc/cgo/test/issue6833.go [new file with mode: 0644]
libgo/misc/cgo/test/issue6833_c.c [new file with mode: 0644]
libgo/misc/cgo/test/issue6997_linux.c [new file with mode: 0644]
libgo/misc/cgo/test/issue6997_linux.go [new file with mode: 0644]
libgo/misc/cgo/test/issue7234_test.go [new file with mode: 0644]
libgo/misc/cgo/test/issue7560.go [new file with mode: 0644]
libgo/misc/cgo/test/issue7665.go [new file with mode: 0644]
libgo/misc/cgo/test/issue7786.go [new file with mode: 0644]
libgo/misc/cgo/test/issue7978.go [new file with mode: 0644]
libgo/misc/cgo/test/issue8092.go [new file with mode: 0644]
libgo/misc/cgo/test/issue8148.go [new file with mode: 0644]
libgo/misc/cgo/test/issue8331.h [new file with mode: 0644]
libgo/misc/cgo/test/issue8331a.go [new file with mode: 0644]
libgo/misc/cgo/test/issue8331b.go [new file with mode: 0644]
libgo/misc/cgo/test/issue8428.go [new file with mode: 0644]
libgo/misc/cgo/test/issue8441.go [new file with mode: 0644]
libgo/misc/cgo/test/issue8517.go [new file with mode: 0644]
libgo/misc/cgo/test/issue8517_windows.c [new file with mode: 0644]
libgo/misc/cgo/test/issue8517_windows.go [new file with mode: 0644]
libgo/misc/cgo/test/issue8694.go [new file with mode: 0644]
libgo/misc/cgo/test/issue8756.go [new file with mode: 0644]
libgo/misc/cgo/test/issue8756/issue8756.go [new file with mode: 0644]
libgo/misc/cgo/test/issue8811.c [new file with mode: 0644]
libgo/misc/cgo/test/issue8811.go [new file with mode: 0644]
libgo/misc/cgo/test/issue8828.go [new file with mode: 0644]
libgo/misc/cgo/test/issue8828/issue8828.c [new file with mode: 0644]
libgo/misc/cgo/test/issue8828/trivial.go [new file with mode: 0644]
libgo/misc/cgo/test/issue8945.go [new file with mode: 0644]
libgo/misc/cgo/test/issue9026.go [new file with mode: 0644]
libgo/misc/cgo/test/issue9026/issue9026.go [new file with mode: 0644]
libgo/misc/cgo/test/issue9400/asm_386.s [new file with mode: 0644]
libgo/misc/cgo/test/issue9400/asm_amd64x.s [new file with mode: 0644]
libgo/misc/cgo/test/issue9400/asm_arm.s [new file with mode: 0644]
libgo/misc/cgo/test/issue9400/asm_arm64.s [new file with mode: 0644]
libgo/misc/cgo/test/issue9400/asm_mips64x.s [new file with mode: 0644]
libgo/misc/cgo/test/issue9400/asm_mipsx.s [new file with mode: 0644]
libgo/misc/cgo/test/issue9400/asm_ppc64x.s [new file with mode: 0644]
libgo/misc/cgo/test/issue9400/asm_s390x.s [new file with mode: 0644]
libgo/misc/cgo/test/issue9400/gccgo.go [new file with mode: 0644]
libgo/misc/cgo/test/issue9400/stubs.go [new file with mode: 0644]
libgo/misc/cgo/test/issue9400_linux.go [new file with mode: 0644]
libgo/misc/cgo/test/issue9510.go [new file with mode: 0644]
libgo/misc/cgo/test/issue9510a/a.go [new file with mode: 0644]
libgo/misc/cgo/test/issue9510b/b.go [new file with mode: 0644]
libgo/misc/cgo/test/issue9557.go [new file with mode: 0644]
libgo/misc/cgo/test/setgid_linux.go [new file with mode: 0644]
libgo/misc/cgo/test/sigaltstack.go [new file with mode: 0644]
libgo/misc/cgo/test/sigprocmask.c [new file with mode: 0644]
libgo/misc/cgo/test/sigprocmask.go [new file with mode: 0644]
libgo/misc/cgo/testasan/main.go [new file with mode: 0644]
libgo/misc/cgo/testcarchive/carchive_test.go [new file with mode: 0644]
libgo/misc/cgo/testcarchive/main.c [new file with mode: 0644]
libgo/misc/cgo/testcarchive/main2.c [new file with mode: 0644]
libgo/misc/cgo/testcarchive/main3.c [new file with mode: 0644]
libgo/misc/cgo/testcarchive/main4.c [new file with mode: 0644]
libgo/misc/cgo/testcarchive/main5.c [new file with mode: 0644]
libgo/misc/cgo/testcarchive/main_unix.c [new file with mode: 0644]
libgo/misc/cgo/testcarchive/main_windows.c [new file with mode: 0644]
libgo/misc/cgo/testcarchive/src/libgo/libgo.go [new file with mode: 0644]
libgo/misc/cgo/testcarchive/src/libgo2/libgo2.go [new file with mode: 0644]
libgo/misc/cgo/testcarchive/src/libgo3/libgo3.go [new file with mode: 0644]
libgo/misc/cgo/testcarchive/src/libgo4/libgo4.go [new file with mode: 0644]
libgo/misc/cgo/testcarchive/src/p/p.go [new file with mode: 0644]
libgo/misc/cgo/testcshared/main0.c [new file with mode: 0644]
libgo/misc/cgo/testcshared/main1.c [new file with mode: 0644]
libgo/misc/cgo/testcshared/main2.c [new file with mode: 0644]
libgo/misc/cgo/testcshared/main3.c [new file with mode: 0644]
libgo/misc/cgo/testcshared/main4.c [new file with mode: 0644]
libgo/misc/cgo/testcshared/main5.c [new file with mode: 0644]
libgo/misc/cgo/testcshared/src/libgo/libgo.go [new file with mode: 0644]
libgo/misc/cgo/testcshared/src/libgo2/dup2.go [new file with mode: 0644]
libgo/misc/cgo/testcshared/src/libgo2/dup3.go [new file with mode: 0644]
libgo/misc/cgo/testcshared/src/libgo2/libgo2.go [new file with mode: 0644]
libgo/misc/cgo/testcshared/src/libgo4/libgo4.go [new file with mode: 0644]
libgo/misc/cgo/testcshared/src/libgo5/libgo5.go [new file with mode: 0644]
libgo/misc/cgo/testcshared/src/p/p.go [new file with mode: 0644]
libgo/misc/cgo/testcshared/test.bash [new file with mode: 0644]
libgo/misc/cgo/testgodefs/anonunion.go [new file with mode: 0644]
libgo/misc/cgo/testgodefs/issue8478.go [new file with mode: 0644]
libgo/misc/cgo/testgodefs/main.go [new file with mode: 0644]
libgo/misc/cgo/testgodefs/test.bash [new file with mode: 0644]
libgo/misc/cgo/testplugin/altpath/src/common/common.go [new file with mode: 0644]
libgo/misc/cgo/testplugin/altpath/src/plugin-mismatch/main.go [new file with mode: 0644]
libgo/misc/cgo/testplugin/src/common/common.go [new file with mode: 0644]
libgo/misc/cgo/testplugin/src/host/host.go [new file with mode: 0644]
libgo/misc/cgo/testplugin/src/iface/main.go [new file with mode: 0644]
libgo/misc/cgo/testplugin/src/iface_a/a.go [new file with mode: 0644]
libgo/misc/cgo/testplugin/src/iface_b/b.go [new file with mode: 0644]
libgo/misc/cgo/testplugin/src/iface_i/i.go [new file with mode: 0644]
libgo/misc/cgo/testplugin/src/issue18676/dynamodbstreamsevt/definition.go [new file with mode: 0644]
libgo/misc/cgo/testplugin/src/issue18676/main.go [new file with mode: 0644]
libgo/misc/cgo/testplugin/src/issue18676/plugin.go [new file with mode: 0644]
libgo/misc/cgo/testplugin/src/plugin1/plugin1.go [new file with mode: 0644]
libgo/misc/cgo/testplugin/src/plugin2/plugin2.go [new file with mode: 0644]
libgo/misc/cgo/testplugin/src/sub/plugin1/plugin1.go [new file with mode: 0644]
libgo/misc/cgo/testplugin/test.bash [new file with mode: 0644]
libgo/misc/cgo/testplugin/unnamed1.go [new file with mode: 0644]
libgo/misc/cgo/testplugin/unnamed2.go [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/msan.go [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/msan2.go [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/msan3.go [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/msan4.go [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/msan5.go [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/msan_fail.go [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/msan_shared.go [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/test.bash [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/tsan.go [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/tsan2.go [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/tsan3.go [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/tsan4.go [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/tsan5.go [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/tsan6.go [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/tsan7.go [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/tsan8.go [new file with mode: 0644]
libgo/misc/cgo/testsanitizers/tsan9.go [new file with mode: 0644]
libgo/misc/cgo/testshared/shared_test.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/dep2/dep2.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/dep3/dep3.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/depBase/asm.s [new file with mode: 0644]
libgo/misc/cgo/testshared/src/depBase/dep.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/depBase/gccgo.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/depBase/stubs.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/exe/exe.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/exe2/exe2.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/exe3/exe3.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/execgo/exe.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/explicit/explicit.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/iface/main.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/iface_a/a.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/iface_b/b.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/iface_i/i.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/implicit/implicit.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/implicitcmd/implicitcmd.go [new file with mode: 0644]
libgo/misc/cgo/testshared/src/trivial/trivial.go [new file with mode: 0644]
libgo/misc/cgo/testsigfwd/main.go [new file with mode: 0644]
libgo/misc/cgo/testso/cgoso.c [new file with mode: 0644]
libgo/misc/cgo/testso/cgoso.go [new file with mode: 0644]
libgo/misc/cgo/testso/cgoso_c.c [new file with mode: 0644]
libgo/misc/cgo/testso/cgoso_unix.go [new file with mode: 0644]
libgo/misc/cgo/testso/main.go [new file with mode: 0644]
libgo/misc/cgo/testsovar/cgoso.go [new file with mode: 0644]
libgo/misc/cgo/testsovar/cgoso_c.c [new file with mode: 0644]
libgo/misc/cgo/testsovar/cgoso_c.h [new file with mode: 0644]
libgo/misc/cgo/testsovar/main.go [new file with mode: 0644]
libgo/misc/cgo/testtls/tls.go [new file with mode: 0644]
libgo/misc/cgo/testtls/tls_test.go [new file with mode: 0644]
libgo/misc/cgo/testtls/tls_unix.c [new file with mode: 0644]

index 38f08feddf72d43bdf7eefb28bffb17605b310fe..583d6032e9361d7d14aca859a3f578509f44971d 100644 (file)
@@ -1,4 +1,4 @@
-bfb18fb16194826bf2bf2d7af873719ddb5e8e42
+040dc31406d580e33f82e578a840600fea5004ef
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index bdf0043f12b9033bc60d5a87b60284f8561135a3..bc24504e2a095e8ebb3dbd79c4165f15c7983494 100755 (executable)
@@ -182,6 +182,13 @@ done
   done
 done
 
+(cd ${NEWDIR}/misc/cgo && find . -type f -print) | while read f; do
+  oldfile=${OLDDIR}/misc/cgo/$f
+  newfile=${NEWDIR}/misc/cgo/$f
+  libgofile=misc/cgo/$f
+  merge $f ${oldfile} ${newfile} ${libgofile}
+done
+
 (cd ${OLDDIR}/src && find . -name '*.go' -print) | while read f; do
   oldfile=${OLDDIR}/src/$f
   newfile=${NEWDIR}/src/$f
@@ -197,5 +204,20 @@ done
   git rm ${libgofile}
 done
 
+(cd ${OLDDIR}/misc/cgo && find . -type f -print) | while read f; do
+  oldfile=${OLDDIR}/misc/cgo/$f
+  newfile=${NEWDIR}/misc/cgo/$f
+  libgofile=misc/cgo/$f
+  if test -f ${newfile}; then
+    continue
+  fi
+  if ! test -f ${libgofile}; then
+    continue
+  fi
+  echo "merge.sh: ${libgofile}: REMOVED"
+  rm -f ${libgofile}
+  git rm ${libgofile}
+done
+
 (echo ${new_rev}; sed -ne '2,$p' MERGE) > MERGE.tmp
 mv MERGE.tmp MERGE
diff --git a/libgo/misc/cgo/errors/err1.go b/libgo/misc/cgo/errors/err1.go
new file mode 100644 (file)
index 0000000..61bbcd2
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2013 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.
+
+package main
+
+/*
+#cgo LDFLAGS: -c
+
+void test() {
+       xxx;            // ERROR HERE
+}
+*/
+import "C"
+
+func main() {
+       C.test()
+}
diff --git a/libgo/misc/cgo/errors/err2.go b/libgo/misc/cgo/errors/err2.go
new file mode 100644 (file)
index 0000000..3ab410b
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2013 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.
+
+package main
+
+import "C"
+
+func main() {
+       s := ""
+       _ = s
+       C.malloc(s) // ERROR HERE
+}
diff --git a/libgo/misc/cgo/errors/err3.go b/libgo/misc/cgo/errors/err3.go
new file mode 100644 (file)
index 0000000..609e1a0
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2014 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.
+
+package main
+
+/*
+typedef struct foo foo_t;
+typedef struct bar bar_t;
+
+foo_t *foop;
+*/
+import "C"
+
+func main() {
+       x := (*C.bar_t)(nil)
+       C.foop = x // ERROR HERE
+}
diff --git a/libgo/misc/cgo/errors/issue11097a.go b/libgo/misc/cgo/errors/issue11097a.go
new file mode 100644 (file)
index 0000000..028d10c
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2015 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.
+
+package main
+
+/*
+//enum test { foo, bar };
+*/
+import "C"
+
+func main() {
+       var a = C.enum_test(1) // ERROR HERE
+       _ = a
+}
diff --git a/libgo/misc/cgo/errors/issue11097b.go b/libgo/misc/cgo/errors/issue11097b.go
new file mode 100644 (file)
index 0000000..b00f24f
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2015 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.
+
+package main
+
+/*
+//enum test { foo, bar };
+*/
+import "C"
+
+func main() {
+       p := new(C.enum_test) // ERROR HERE
+       _ = p
+}
diff --git a/libgo/misc/cgo/errors/issue13129.go b/libgo/misc/cgo/errors/issue13129.go
new file mode 100644 (file)
index 0000000..f7ad7a7
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2015 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.
+
+// issue 13129: used to output error about C.unsignedshort with CC=clang
+
+package main
+
+import "C"
+
+func main() {
+       var x C.ushort
+       x = int(0) // ERROR HERE
+}
diff --git a/libgo/misc/cgo/errors/issue13423.go b/libgo/misc/cgo/errors/issue13423.go
new file mode 100644 (file)
index 0000000..fc19157
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2015 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.
+
+package main
+
+// #include <stdio.h>
+import "C"
+
+func main() {
+       _ = C.fopen() // ERROR HERE
+}
diff --git a/libgo/misc/cgo/errors/issue13635.go b/libgo/misc/cgo/errors/issue13635.go
new file mode 100644 (file)
index 0000000..0ce2b1e
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2015 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.
+
+// issue 13635: used to output error about C.unsignedchar.
+// This test tests all such types.
+
+package pkg
+
+import "C"
+
+func main() {
+       var (
+               _ C.uchar         = "uc"  // ERROR HERE
+               _ C.schar         = "sc"  // ERROR HERE
+               _ C.ushort        = "us"  // ERROR HERE
+               _ C.uint          = "ui"  // ERROR HERE
+               _ C.ulong         = "ul"  // ERROR HERE
+               _ C.longlong      = "ll"  // ERROR HERE
+               _ C.ulonglong     = "ull" // ERROR HERE
+               _ C.complexfloat  = "cf"  // ERROR HERE
+               _ C.complexdouble = "cd"  // ERROR HERE
+       )
+}
diff --git a/libgo/misc/cgo/errors/issue13830.go b/libgo/misc/cgo/errors/issue13830.go
new file mode 100644 (file)
index 0000000..ac20c82
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+// cgo converts C void* to Go unsafe.Pointer, so despite appearances C
+// void** is Go *unsafe.Pointer. This test verifies that we detect the
+// problem at build time.
+
+package main
+
+// typedef void v;
+// void F(v** p) {}
+import "C"
+
+import "unsafe"
+
+type v [0]byte
+
+func f(p **v) {
+       C.F((**C.v)(unsafe.Pointer(p))) // ERROR HERE
+}
+
+func main() {
+       var p *v
+       f(&p)
+}
diff --git a/libgo/misc/cgo/errors/issue14669.go b/libgo/misc/cgo/errors/issue14669.go
new file mode 100644 (file)
index 0000000..04d2bcb
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2016 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.
+
+// Issue 14669: test that fails when build with CGO_CFLAGS selecting
+// optimization.
+
+package p
+
+/*
+const int E = 1;
+
+typedef struct s {
+       int       c;
+} s;
+*/
+import "C"
+
+func F() {
+       _ = C.s{
+               c: C.E,
+       }
+}
diff --git a/libgo/misc/cgo/errors/issue16116.go b/libgo/misc/cgo/errors/issue16116.go
new file mode 100644 (file)
index 0000000..1e01cab
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2016 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.
+
+package main
+
+// void f(void *p, int x) {}
+import "C"
+
+func main() {
+       _ = C.f(1) // ERROR HERE
+}
diff --git a/libgo/misc/cgo/errors/issue16591.go b/libgo/misc/cgo/errors/issue16591.go
new file mode 100644 (file)
index 0000000..10eb840
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2016 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.
+
+// Issue 16591: Test that we detect an invalid call that was being
+// hidden by a type conversion inserted by cgo checking.
+
+package p
+
+// void f(int** p) { }
+import "C"
+
+type x *C.int
+
+func F(p *x) {
+       C.f(p) // ERROR HERE
+}
diff --git a/libgo/misc/cgo/errors/issue7757.go b/libgo/misc/cgo/errors/issue7757.go
new file mode 100644 (file)
index 0000000..0426e9f
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2014 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.
+
+package main
+
+/*
+void foo() {}
+*/
+import "C"
+
+func main() {
+       C.foo = C.foo // ERROR HERE
+}
diff --git a/libgo/misc/cgo/errors/issue8442.go b/libgo/misc/cgo/errors/issue8442.go
new file mode 100644 (file)
index 0000000..60477ad
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2014 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.
+
+package main
+
+// Issue 8442.  Cgo output unhelpful error messages for
+// invalid C preambles.
+
+/*
+void issue8442foo(UNDEF*); // ERROR HERE
+*/
+import "C"
+
+func main() {
+       C.issue8442foo(nil)
+}
diff --git a/libgo/misc/cgo/errors/malloc.go b/libgo/misc/cgo/errors/malloc.go
new file mode 100644 (file)
index 0000000..65da020
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2016 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.
+
+// Test that C.malloc does not return nil.
+
+package main
+
+// #include <stdlib.h>
+import "C"
+
+import (
+       "fmt"
+       "runtime"
+)
+
+func main() {
+       var size C.size_t
+       size--
+
+       // The Dragonfly libc succeeds when asked to allocate
+       // 0xffffffffffffffff bytes, so pass a different value that
+       // causes it to fail.
+       if runtime.GOOS == "dragonfly" {
+               size = C.size_t(0x7fffffff << (32 * (^uintptr(0) >> 63)))
+       }
+
+       p := C.malloc(size)
+       if p == nil {
+               fmt.Println("malloc: C.malloc returned nil")
+               // Just exit normally--the test script expects this
+               // program to crash, so exiting normally indicates failure.
+       }
+}
diff --git a/libgo/misc/cgo/errors/ptr.go b/libgo/misc/cgo/errors/ptr.go
new file mode 100644 (file)
index 0000000..4dafbdf
--- /dev/null
@@ -0,0 +1,576 @@
+// Copyright 2015 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.
+
+// Tests that cgo detects invalid pointer passing at runtime.
+
+package main
+
+import (
+       "bufio"
+       "bytes"
+       "fmt"
+       "io"
+       "io/ioutil"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "runtime"
+       "strings"
+       "sync"
+)
+
+// ptrTest is the tests without the boilerplate.
+type ptrTest struct {
+       name      string   // for reporting
+       c         string   // the cgo comment
+       imports   []string // a list of imports
+       support   string   // supporting functions
+       body      string   // the body of the main function
+       extra     []extra  // extra files
+       fail      bool     // whether the test should fail
+       expensive bool     // whether the test requires the expensive check
+}
+
+type extra struct {
+       name     string
+       contents string
+}
+
+var ptrTests = []ptrTest{
+       {
+               // Passing a pointer to a struct that contains a Go pointer.
+               name: "ptr1",
+               c:    `typedef struct s { int *p; } s; void f(s *ps) {}`,
+               body: `C.f(&C.s{new(C.int)})`,
+               fail: true,
+       },
+       {
+               // Passing a pointer to a struct that contains a Go pointer.
+               name: "ptr2",
+               c:    `typedef struct s { int *p; } s; void f(s *ps) {}`,
+               body: `p := &C.s{new(C.int)}; C.f(p)`,
+               fail: true,
+       },
+       {
+               // Passing a pointer to an int field of a Go struct
+               // that (irrelevantly) contains a Go pointer.
+               name: "ok1",
+               c:    `struct s { int i; int *p; }; void f(int *p) {}`,
+               body: `p := &C.struct_s{i: 0, p: new(C.int)}; C.f(&p.i)`,
+               fail: false,
+       },
+       {
+               // Passing a pointer to a pointer field of a Go struct.
+               name: "ptr-field",
+               c:    `struct s { int i; int *p; }; void f(int **p) {}`,
+               body: `p := &C.struct_s{i: 0, p: new(C.int)}; C.f(&p.p)`,
+               fail: true,
+       },
+       {
+               // Passing a pointer to a pointer field of a Go
+               // struct, where the field does not contain a Go
+               // pointer, but another field (irrelevantly) does.
+               name: "ptr-field-ok",
+               c:    `struct s { int *p1; int *p2; }; void f(int **p) {}`,
+               body: `p := &C.struct_s{p1: nil, p2: new(C.int)}; C.f(&p.p1)`,
+               fail: false,
+       },
+       {
+               // Passing the address of a slice with no Go pointers.
+               name:    "slice-ok-1",
+               c:       `void f(void **p) {}`,
+               imports: []string{"unsafe"},
+               body:    `s := []unsafe.Pointer{nil}; C.f(&s[0])`,
+               fail:    false,
+       },
+       {
+               // Passing the address of a slice with a Go pointer.
+               name:    "slice-ptr-1",
+               c:       `void f(void **p) {}`,
+               imports: []string{"unsafe"},
+               body:    `i := 0; s := []unsafe.Pointer{unsafe.Pointer(&i)}; C.f(&s[0])`,
+               fail:    true,
+       },
+       {
+               // Passing the address of a slice with a Go pointer,
+               // where we are passing the address of an element that
+               // is not a Go pointer.
+               name:    "slice-ptr-2",
+               c:       `void f(void **p) {}`,
+               imports: []string{"unsafe"},
+               body:    `i := 0; s := []unsafe.Pointer{nil, unsafe.Pointer(&i)}; C.f(&s[0])`,
+               fail:    true,
+       },
+       {
+               // Passing the address of a slice that is an element
+               // in a struct only looks at the slice.
+               name:    "slice-ok-2",
+               c:       `void f(void **p) {}`,
+               imports: []string{"unsafe"},
+               support: `type S struct { p *int; s []unsafe.Pointer }`,
+               body:    `i := 0; p := &S{p:&i, s:[]unsafe.Pointer{nil}}; C.f(&p.s[0])`,
+               fail:    false,
+       },
+       {
+               // Passing the address of a slice of an array that is
+               // an element in a struct, with a type conversion.
+               name:    "slice-ok-3",
+               c:       `void f(void* p) {}`,
+               imports: []string{"unsafe"},
+               support: `type S struct { p *int; a [4]byte }`,
+               body:    `i := 0; p := &S{p:&i}; s := p.a[:]; C.f(unsafe.Pointer(&s[0]))`,
+               fail:    false,
+       },
+       {
+               // Passing the address of a slice of an array that is
+               // an element in a struct, with a type conversion.
+               name:    "slice-ok-4",
+               c:       `typedef void* PV; void f(PV p) {}`,
+               imports: []string{"unsafe"},
+               support: `type S struct { p *int; a [4]byte }`,
+               body:    `i := 0; p := &S{p:&i}; C.f(C.PV(unsafe.Pointer(&p.a[0])))`,
+               fail:    false,
+       },
+       {
+               // Passing the address of a static variable with no
+               // pointers doesn't matter.
+               name:    "varok",
+               c:       `void f(char** parg) {}`,
+               support: `var hello = [...]C.char{'h', 'e', 'l', 'l', 'o'}`,
+               body:    `parg := [1]*C.char{&hello[0]}; C.f(&parg[0])`,
+               fail:    false,
+       },
+       {
+               // Passing the address of a static variable with
+               // pointers does matter.
+               name:    "var",
+               c:       `void f(char*** parg) {}`,
+               support: `var hello = [...]*C.char{new(C.char)}`,
+               body:    `parg := [1]**C.char{&hello[0]}; C.f(&parg[0])`,
+               fail:    true,
+       },
+       {
+               // Storing a Go pointer into C memory should fail.
+               name: "barrier",
+               c: `#include <stdlib.h>
+                    char **f1() { return malloc(sizeof(char*)); }
+                    void f2(char **p) {}`,
+               body:      `p := C.f1(); *p = new(C.char); C.f2(p)`,
+               fail:      true,
+               expensive: true,
+       },
+       {
+               // Storing a Go pointer into C memory by assigning a
+               // large value should fail.
+               name: "barrier-struct",
+               c: `#include <stdlib.h>
+                    struct s { char *a[10]; };
+                    struct s *f1() { return malloc(sizeof(struct s)); }
+                    void f2(struct s *p) {}`,
+               body:      `p := C.f1(); p.a = [10]*C.char{new(C.char)}; C.f2(p)`,
+               fail:      true,
+               expensive: true,
+       },
+       {
+               // Storing a Go pointer into C memory using a slice
+               // copy should fail.
+               name: "barrier-slice",
+               c: `#include <stdlib.h>
+                    struct s { char *a[10]; };
+                    struct s *f1() { return malloc(sizeof(struct s)); }
+                    void f2(struct s *p) {}`,
+               body:      `p := C.f1(); copy(p.a[:], []*C.char{new(C.char)}); C.f2(p)`,
+               fail:      true,
+               expensive: true,
+       },
+       {
+               // A very large value uses a GC program, which is a
+               // different code path.
+               name: "barrier-gcprog-array",
+               c: `#include <stdlib.h>
+                    struct s { char *a[32769]; };
+                    struct s *f1() { return malloc(sizeof(struct s)); }
+                    void f2(struct s *p) {}`,
+               body:      `p := C.f1(); p.a = [32769]*C.char{new(C.char)}; C.f2(p)`,
+               fail:      true,
+               expensive: true,
+       },
+       {
+               // Similar case, with a source on the heap.
+               name: "barrier-gcprog-array-heap",
+               c: `#include <stdlib.h>
+                    struct s { char *a[32769]; };
+                    struct s *f1() { return malloc(sizeof(struct s)); }
+                    void f2(struct s *p) {}
+                    void f3(void *p) {}`,
+               imports:   []string{"unsafe"},
+               body:      `p := C.f1(); n := &[32769]*C.char{new(C.char)}; p.a = *n; C.f2(p); n[0] = nil; C.f3(unsafe.Pointer(n))`,
+               fail:      true,
+               expensive: true,
+       },
+       {
+               // A GC program with a struct.
+               name: "barrier-gcprog-struct",
+               c: `#include <stdlib.h>
+                    struct s { char *a[32769]; };
+                    struct s2 { struct s f; };
+                    struct s2 *f1() { return malloc(sizeof(struct s2)); }
+                    void f2(struct s2 *p) {}`,
+               body:      `p := C.f1(); p.f = C.struct_s{[32769]*C.char{new(C.char)}}; C.f2(p)`,
+               fail:      true,
+               expensive: true,
+       },
+       {
+               // Similar case, with a source on the heap.
+               name: "barrier-gcprog-struct-heap",
+               c: `#include <stdlib.h>
+                    struct s { char *a[32769]; };
+                    struct s2 { struct s f; };
+                    struct s2 *f1() { return malloc(sizeof(struct s2)); }
+                    void f2(struct s2 *p) {}
+                    void f3(void *p) {}`,
+               imports:   []string{"unsafe"},
+               body:      `p := C.f1(); n := &C.struct_s{[32769]*C.char{new(C.char)}}; p.f = *n; C.f2(p); n.a[0] = nil; C.f3(unsafe.Pointer(n))`,
+               fail:      true,
+               expensive: true,
+       },
+       {
+               // Exported functions may not return Go pointers.
+               name: "export1",
+               c:    `extern unsigned char *GoFn();`,
+               support: `//export GoFn
+                          func GoFn() *byte { return new(byte) }`,
+               body: `C.GoFn()`,
+               fail: true,
+       },
+       {
+               // Returning a C pointer is fine.
+               name: "exportok",
+               c: `#include <stdlib.h>
+                    extern unsigned char *GoFn();`,
+               support: `//export GoFn
+                          func GoFn() *byte { return (*byte)(C.malloc(1)) }`,
+               body: `C.GoFn()`,
+       },
+       {
+               // Passing a Go string is fine.
+               name: "pass-string",
+               c: `#include <stddef.h>
+                    typedef struct { const char *p; ptrdiff_t n; } gostring;
+                    gostring f(gostring s) { return s; }`,
+               imports: []string{"unsafe"},
+               body:    `s := "a"; r := C.f(*(*C.gostring)(unsafe.Pointer(&s))); if *(*string)(unsafe.Pointer(&r)) != s { panic(r) }`,
+       },
+       {
+               // Passing a slice of Go strings fails.
+               name:    "pass-string-slice",
+               c:       `void f(void *p) {}`,
+               imports: []string{"strings", "unsafe"},
+               support: `type S struct { a [1]string }`,
+               body:    `s := S{a:[1]string{strings.Repeat("a", 2)}}; C.f(unsafe.Pointer(&s.a[0]))`,
+               fail:    true,
+       },
+       {
+               // Exported functions may not return strings.
+               name:    "ret-string",
+               c:       `extern void f();`,
+               imports: []string{"strings"},
+               support: `//export GoStr
+                          func GoStr() string { return strings.Repeat("a", 2) }`,
+               body: `C.f()`,
+               extra: []extra{
+                       {
+                               "call.c",
+                               `#include <stddef.h>
+                                 typedef struct { const char *p; ptrdiff_t n; } gostring;
+                                 extern gostring GoStr();
+                                 void f() { GoStr(); }`,
+                       },
+               },
+               fail: true,
+       },
+       {
+               // Don't check non-pointer data.
+               // Uses unsafe code to get a pointer we shouldn't check.
+               // Although we use unsafe, the uintptr represents an integer
+               // that happens to have the same representation as a pointer;
+               // that is, we are testing something that is not unsafe.
+               name: "ptrdata1",
+               c: `#include <stdlib.h>
+                    void f(void* p) {}`,
+               imports: []string{"unsafe"},
+               support: `type S struct { p *int; a [8*8]byte; u uintptr }`,
+               body:    `i := 0; p := &S{u:uintptr(unsafe.Pointer(&i))}; q := (*S)(C.malloc(C.size_t(unsafe.Sizeof(*p)))); *q = *p; C.f(unsafe.Pointer(q))`,
+               fail:    false,
+       },
+       {
+               // Like ptrdata1, but with a type that uses a GC program.
+               name: "ptrdata2",
+               c: `#include <stdlib.h>
+                    void f(void* p) {}`,
+               imports: []string{"unsafe"},
+               support: `type S struct { p *int; a [32769*8]byte; q *int; u uintptr }`,
+               body:    `i := 0; p := S{u:uintptr(unsafe.Pointer(&i))}; q := (*S)(C.malloc(C.size_t(unsafe.Sizeof(p)))); *q = p; C.f(unsafe.Pointer(q))`,
+               fail:    false,
+       },
+       {
+               // Check deferred pointers when they are used, not
+               // when the defer statement is run.
+               name: "defer",
+               c:    `typedef struct s { int *p; } s; void f(s *ps) {}`,
+               body: `p := &C.s{}; defer C.f(p); p.p = new(C.int)`,
+               fail: true,
+       },
+       {
+               // Check a pointer to a union if the union has any
+               // pointer fields.
+               name:    "union1",
+               c:       `typedef union { char **p; unsigned long i; } u; void f(u *pu) {}`,
+               imports: []string{"unsafe"},
+               body:    `var b C.char; p := &b; C.f((*C.u)(unsafe.Pointer(&p)))`,
+               fail:    true,
+       },
+       {
+               // Don't check a pointer to a union if the union does
+               // not have any pointer fields.
+               // Like ptrdata1 above, the uintptr represents an
+               // integer that happens to have the same
+               // representation as a pointer.
+               name:    "union2",
+               c:       `typedef union { unsigned long i; } u; void f(u *pu) {}`,
+               imports: []string{"unsafe"},
+               body:    `var b C.char; p := &b; C.f((*C.u)(unsafe.Pointer(&p)))`,
+               fail:    false,
+       },
+}
+
+func main() {
+       os.Exit(doTests())
+}
+
+func doTests() int {
+       gopath, err := ioutil.TempDir("", "cgoerrors")
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               return 2
+       }
+       defer os.RemoveAll(gopath)
+
+       if err := os.MkdirAll(filepath.Join(gopath, "src"), 0777); err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               return 2
+       }
+
+       workers := runtime.NumCPU() + 1
+
+       var wg sync.WaitGroup
+       c := make(chan int)
+       errs := make(chan int)
+       for i := 0; i < workers; i++ {
+               wg.Add(1)
+               go func() {
+                       worker(gopath, c, errs)
+                       wg.Done()
+               }()
+       }
+
+       for i := range ptrTests {
+               c <- i
+       }
+       close(c)
+
+       go func() {
+               wg.Wait()
+               close(errs)
+       }()
+
+       tot := 0
+       for e := range errs {
+               tot += e
+       }
+       return tot
+}
+
+func worker(gopath string, c, errs chan int) {
+       e := 0
+       for i := range c {
+               if !doOne(gopath, i) {
+                       e++
+               }
+       }
+       if e > 0 {
+               errs <- e
+       }
+}
+
+func doOne(gopath string, i int) bool {
+       t := &ptrTests[i]
+
+       dir := filepath.Join(gopath, "src", fmt.Sprintf("dir%d", i))
+       if err := os.Mkdir(dir, 0777); err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               return false
+       }
+
+       name := filepath.Join(dir, fmt.Sprintf("t%d.go", i))
+       f, err := os.Create(name)
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               return false
+       }
+
+       b := bufio.NewWriter(f)
+       fmt.Fprintln(b, `package main`)
+       fmt.Fprintln(b)
+       fmt.Fprintln(b, `/*`)
+       fmt.Fprintln(b, t.c)
+       fmt.Fprintln(b, `*/`)
+       fmt.Fprintln(b, `import "C"`)
+       fmt.Fprintln(b)
+       for _, imp := range t.imports {
+               fmt.Fprintln(b, `import "`+imp+`"`)
+       }
+       if len(t.imports) > 0 {
+               fmt.Fprintln(b)
+       }
+       if len(t.support) > 0 {
+               fmt.Fprintln(b, t.support)
+               fmt.Fprintln(b)
+       }
+       fmt.Fprintln(b, `func main() {`)
+       fmt.Fprintln(b, t.body)
+       fmt.Fprintln(b, `}`)
+
+       if err := b.Flush(); err != nil {
+               fmt.Fprintf(os.Stderr, "flushing %s: %v\n", name, err)
+               return false
+       }
+       if err := f.Close(); err != nil {
+               fmt.Fprintf(os.Stderr, "closing %s: %v\n", name, err)
+               return false
+       }
+
+       for _, e := range t.extra {
+               if err := ioutil.WriteFile(filepath.Join(dir, e.name), []byte(e.contents), 0644); err != nil {
+                       fmt.Fprintf(os.Stderr, "writing %s: %v\n", e.name, err)
+                       return false
+               }
+       }
+
+       ok := true
+
+       cmd := exec.Command("go", "build")
+       cmd.Dir = dir
+       cmd.Env = addEnv("GOPATH", gopath)
+       buf, err := cmd.CombinedOutput()
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "test %s failed to build: %v\n%s", t.name, err, buf)
+               return false
+       }
+
+       exe := filepath.Join(dir, filepath.Base(dir))
+       cmd = exec.Command(exe)
+       cmd.Dir = dir
+
+       if t.expensive {
+               cmd.Env = cgocheckEnv("1")
+               buf, err := cmd.CombinedOutput()
+               if err != nil {
+                       var errbuf bytes.Buffer
+                       if t.fail {
+                               fmt.Fprintf(&errbuf, "test %s marked expensive but failed when not expensive: %v\n", t.name, err)
+                       } else {
+                               fmt.Fprintf(&errbuf, "test %s failed unexpectedly with GODEBUG=cgocheck=1: %v\n", t.name, err)
+                       }
+                       reportTestOutput(&errbuf, t.name, buf)
+                       os.Stderr.Write(errbuf.Bytes())
+                       ok = false
+               }
+
+               cmd = exec.Command(exe)
+               cmd.Dir = dir
+       }
+
+       if t.expensive {
+               cmd.Env = cgocheckEnv("2")
+       }
+
+       buf, err = cmd.CombinedOutput()
+
+       if t.fail {
+               if err == nil {
+                       var errbuf bytes.Buffer
+                       fmt.Fprintf(&errbuf, "test %s did not fail as expected\n", t.name)
+                       reportTestOutput(&errbuf, t.name, buf)
+                       os.Stderr.Write(errbuf.Bytes())
+                       ok = false
+               } else if !bytes.Contains(buf, []byte("Go pointer")) {
+                       var errbuf bytes.Buffer
+                       fmt.Fprintf(&errbuf, "test %s output does not contain expected error (failed with %v)\n", t.name, err)
+                       reportTestOutput(&errbuf, t.name, buf)
+                       os.Stderr.Write(errbuf.Bytes())
+                       ok = false
+               }
+       } else {
+               if err != nil {
+                       var errbuf bytes.Buffer
+                       fmt.Fprintf(&errbuf, "test %s failed unexpectedly: %v\n", t.name, err)
+                       reportTestOutput(&errbuf, t.name, buf)
+                       os.Stderr.Write(errbuf.Bytes())
+                       ok = false
+               }
+
+               if !t.expensive && ok {
+                       // Make sure it passes with the expensive checks.
+                       cmd := exec.Command(exe)
+                       cmd.Dir = dir
+                       cmd.Env = cgocheckEnv("2")
+                       buf, err := cmd.CombinedOutput()
+                       if err != nil {
+                               var errbuf bytes.Buffer
+                               fmt.Fprintf(&errbuf, "test %s failed unexpectedly with expensive checks: %v\n", t.name, err)
+                               reportTestOutput(&errbuf, t.name, buf)
+                               os.Stderr.Write(errbuf.Bytes())
+                               ok = false
+                       }
+               }
+       }
+
+       if t.fail && ok {
+               cmd = exec.Command(exe)
+               cmd.Dir = dir
+               cmd.Env = cgocheckEnv("0")
+               buf, err := cmd.CombinedOutput()
+               if err != nil {
+                       var errbuf bytes.Buffer
+                       fmt.Fprintf(&errbuf, "test %s failed unexpectedly with GODEBUG=cgocheck=0: %v\n", t.name, err)
+                       reportTestOutput(&errbuf, t.name, buf)
+                       os.Stderr.Write(errbuf.Bytes())
+                       ok = false
+               }
+       }
+
+       return ok
+}
+
+func reportTestOutput(w io.Writer, name string, buf []byte) {
+       fmt.Fprintf(w, "=== test %s output ===\n", name)
+       fmt.Fprintf(w, "%s", buf)
+       fmt.Fprintf(w, "=== end of test %s output ===\n", name)
+}
+
+func cgocheckEnv(val string) []string {
+       return addEnv("GODEBUG", "cgocheck="+val)
+}
+
+func addEnv(key, val string) []string {
+       env := []string{key + "=" + val}
+       look := key + "="
+       for _, e := range os.Environ() {
+               if !strings.HasPrefix(e, look) {
+                       env = append(env, e)
+               }
+       }
+       return env
+}
diff --git a/libgo/misc/cgo/errors/test.bash b/libgo/misc/cgo/errors/test.bash
new file mode 100644 (file)
index 0000000..05261e9
--- /dev/null
@@ -0,0 +1,73 @@
+#!/usr/bin/env bash
+
+# Copyright 2013 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.
+
+check() {
+       file=$1
+       line=$(grep -n 'ERROR HERE' $file | sed 's/:.*//')
+       if [ "$line" = "" ]; then
+               echo 1>&2 misc/cgo/errors/test.bash: BUG: cannot find ERROR HERE in $file
+               exit 1
+       fi
+       expect $file $file:$line:
+}
+
+expect() {
+       file=$1
+       shift
+       if go build $file >errs 2>&1; then
+               echo 1>&2 misc/cgo/errors/test.bash: BUG: expected cgo to fail on $file but it succeeded
+               exit 1
+       fi
+       if ! test -s errs; then
+               echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output for $file but saw none
+               exit 1
+       fi
+       for error; do
+               if ! fgrep $error errs >/dev/null 2>&1; then
+                       echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output for $file to contain \"$error\" but saw:
+                       cat 1>&2 errs
+                       exit 1
+               fi
+       done
+}
+
+check err1.go
+check err2.go
+check err3.go
+check issue7757.go
+check issue8442.go
+check issue11097a.go
+check issue11097b.go
+expect issue13129.go C.ushort
+check issue13423.go
+expect issue13635.go C.uchar C.schar C.ushort C.uint C.ulong C.longlong C.ulonglong C.complexfloat C.complexdouble
+check issue13830.go
+check issue16116.go
+check issue16591.go
+
+if ! go build issue14669.go; then
+       exit 1
+fi
+if ! CGO_CFLAGS="-O" go build issue14669.go; then
+       exit 1
+fi
+
+if ! go run ptr.go; then
+       exit 1
+fi
+
+# The malloc.go test should crash.
+rm -f malloc.out
+if go run malloc.go >malloc.out 2>&1; then
+       echo '`go run malloc.go` succeeded unexpectedly'
+       cat malloc.out
+       rm -f malloc.out
+       exit 1
+fi
+rm -f malloc.out
+
+rm -rf errs _obj
+exit 0
diff --git a/libgo/misc/cgo/fortran/answer.f90 b/libgo/misc/cgo/fortran/answer.f90
new file mode 100644 (file)
index 0000000..b3717ee
--- /dev/null
@@ -0,0 +1,9 @@
+! Copyright 2016 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.
+
+function the_answer() result(j) bind(C)
+  use iso_c_binding, only: c_int
+  integer(c_int) :: j ! output
+  j = 42
+end function the_answer
diff --git a/libgo/misc/cgo/fortran/fortran.go b/libgo/misc/cgo/fortran/fortran.go
new file mode 100644 (file)
index 0000000..0079b53
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2016 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.
+
+package fortran
+
+// int the_answer();
+import "C"
+
+func TheAnswer() int {
+       return int(C.the_answer())
+}
diff --git a/libgo/misc/cgo/fortran/fortran_test.go b/libgo/misc/cgo/fortran/fortran_test.go
new file mode 100644 (file)
index 0000000..d0cb9f2
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2016 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.
+
+package fortran
+
+import "testing"
+
+func TestFortran(t *testing.T) {
+       if a := TheAnswer(); a != 42 {
+               t.Errorf("Unexpected result for The Answer. Got: %d Want: 42", a)
+       }
+}
diff --git a/libgo/misc/cgo/fortran/helloworld/helloworld.f90 b/libgo/misc/cgo/fortran/helloworld/helloworld.f90
new file mode 100644 (file)
index 0000000..cbc34c1
--- /dev/null
@@ -0,0 +1,3 @@
+      program HelloWorldF90
+              write(*,*) "Hello World!"
+      end program HelloWorldF90
diff --git a/libgo/misc/cgo/fortran/test.bash b/libgo/misc/cgo/fortran/test.bash
new file mode 100644 (file)
index 0000000..3d1bc9d
--- /dev/null
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+# Copyright 2016 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.
+
+# This directory is intended to test the use of Fortran with cgo.
+
+set -e
+
+FC=$1
+
+goos=$(go env GOOS)
+
+libext="so"
+if [ "$goos" == "darwin" ]; then
+       libext="dylib"
+fi
+
+case "$FC" in
+*gfortran*)
+  libpath=$(dirname $($FC -print-file-name=libgfortran.$libext))
+  export CGO_LDFLAGS="$CGO_LDFLAGS -Wl,-rpath,$libpath -L $libpath"
+  ;;
+esac
+
+if ! $FC helloworld/helloworld.f90 -o main.exe >& /dev/null; then
+  echo "skipping Fortran test: could not build helloworld.f90 with $FC"
+  exit 0
+fi
+rm -f main.exe
+
+status=0
+
+if ! go test; then
+  echo "FAIL: go test"
+  status=1
+fi
+
+exit $status
diff --git a/libgo/misc/cgo/gmp/fib.go b/libgo/misc/cgo/gmp/fib.go
new file mode 100644 (file)
index 0000000..f1091b1
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright 2009 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 ignore
+
+// Compute Fibonacci numbers with two goroutines
+// that pass integers back and forth.  No actual
+// concurrency, just threads and synchronization
+// and foreign code on multiple pthreads.
+
+package main
+
+import (
+       big "."
+       "runtime"
+)
+
+func fibber(c chan *big.Int, out chan string, n int64) {
+       // Keep the fibbers in dedicated operating system
+       // threads, so that this program tests coordination
+       // between pthreads and not just goroutines.
+       runtime.LockOSThread()
+
+       i := big.NewInt(n)
+       if n == 0 {
+               c <- i
+       }
+       for {
+               j := <-c
+               out <- j.String()
+               i.Add(i, j)
+               c <- i
+       }
+}
+
+func main() {
+       c := make(chan *big.Int)
+       out := make(chan string)
+       go fibber(c, out, 0)
+       go fibber(c, out, 1)
+       for i := 0; i < 200; i++ {
+               println(<-out)
+       }
+}
diff --git a/libgo/misc/cgo/gmp/gmp.go b/libgo/misc/cgo/gmp/gmp.go
new file mode 100644 (file)
index 0000000..971a10a
--- /dev/null
@@ -0,0 +1,380 @@
+// Copyright 2009 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.
+
+/*
+An example of wrapping a C library in Go. This is the GNU
+multiprecision library gmp's integer type mpz_t wrapped to look like
+the Go package big's integer type Int.
+
+This is a syntactically valid Go program—it can be parsed with the Go
+parser and processed by godoc—but it is not compiled directly by gc.
+Instead, a separate tool, cgo, processes it to produce three output
+files.  The first two, 6g.go and 6c.c, are a Go source file for 6g and
+a C source file for 6c; both compile as part of the named package
+(gmp, in this example).  The third, gcc.c, is a C source file for gcc;
+it compiles into a shared object (.so) that is dynamically linked into
+any 6.out that imports the first two files.
+
+The stanza
+
+       // #include <gmp.h>
+       import "C"
+
+is a signal to cgo.  The doc comment on the import of "C" provides
+additional context for the C file.  Here it is just a single #include
+but it could contain arbitrary C definitions to be imported and used.
+
+Cgo recognizes any use of a qualified identifier C.xxx and uses gcc to
+find the definition of xxx.  If xxx is a type, cgo replaces C.xxx with
+a Go translation.  C arithmetic types translate to precisely-sized Go
+arithmetic types.  A C struct translates to a Go struct, field by
+field; unrepresentable fields are replaced with opaque byte arrays.  A
+C union translates into a struct containing the first union member and
+perhaps additional padding.  C arrays become Go arrays.  C pointers
+become Go pointers.  C function pointers become Go's uintptr.
+C void pointers become Go's unsafe.Pointer.
+
+For example, mpz_t is defined in <gmp.h> as:
+
+       typedef unsigned long int mp_limb_t;
+
+       typedef struct
+       {
+               int _mp_alloc;
+               int _mp_size;
+               mp_limb_t *_mp_d;
+       } __mpz_struct;
+
+       typedef __mpz_struct mpz_t[1];
+
+Cgo generates:
+
+       type _C_int int32
+       type _C_mp_limb_t uint64
+       type _C___mpz_struct struct {
+               _mp_alloc _C_int;
+               _mp_size _C_int;
+               _mp_d *_C_mp_limb_t;
+       }
+       type _C_mpz_t [1]_C___mpz_struct
+
+and then replaces each occurrence of a type C.xxx with _C_xxx.
+
+If xxx is data, cgo arranges for C.xxx to refer to the C variable,
+with the type translated as described above.  To do this, cgo must
+introduce a Go variable that points at the C variable (the linker can
+be told to initialize this pointer).  For example, if the gmp library
+provided
+
+       mpz_t zero;
+
+then cgo would rewrite a reference to C.zero by introducing
+
+       var _C_zero *C.mpz_t
+
+and then replacing all instances of C.zero with (*_C_zero).
+
+Cgo's most interesting translation is for functions.  If xxx is a C
+function, then cgo rewrites C.xxx into a new function _C_xxx that
+calls the C xxx in a standard pthread.  The new function translates
+its arguments, calls xxx, and translates the return value.
+
+Translation of parameters and the return value follows the type
+translation above except that arrays passed as parameters translate
+explicitly in Go to pointers to arrays, as they do (implicitly) in C.
+
+Garbage collection is the big problem.  It is fine for the Go world to
+have pointers into the C world and to free those pointers when they
+are no longer needed.  To help, the Go code can define Go objects
+holding the C pointers and use runtime.SetFinalizer on those Go objects.
+
+It is much more difficult for the C world to have pointers into the Go
+world, because the Go garbage collector is unaware of the memory
+allocated by C.  The most important consideration is not to
+constrain future implementations, so the rule is that Go code can
+hand a Go pointer to C code but must separately arrange for
+Go to hang on to a reference to the pointer until C is done with it.
+*/
+package gmp
+
+/*
+#cgo LDFLAGS: -lgmp
+#include <gmp.h>
+#include <stdlib.h>
+
+// gmp 5.0.0+ changed the type of the 3rd argument to mp_bitcnt_t,
+// so, to support older versions, we wrap these two functions.
+void _mpz_mul_2exp(mpz_ptr a, mpz_ptr b, unsigned long n) {
+       mpz_mul_2exp(a, b, n);
+}
+void _mpz_div_2exp(mpz_ptr a, mpz_ptr b, unsigned long n) {
+       mpz_div_2exp(a, b, n);
+}
+*/
+import "C"
+
+import (
+       "os"
+       "unsafe"
+)
+
+/*
+ * one of a kind
+ */
+
+// An Int represents a signed multi-precision integer.
+// The zero value for an Int represents the value 0.
+type Int struct {
+       i    C.mpz_t
+       init bool
+}
+
+// NewInt returns a new Int initialized to x.
+func NewInt(x int64) *Int { return new(Int).SetInt64(x) }
+
+// Int promises that the zero value is a 0, but in gmp
+// the zero value is a crash.  To bridge the gap, the
+// init bool says whether this is a valid gmp value.
+// doinit initializes z.i if it needs it.  This is not inherent
+// to FFI, just a mismatch between Go's convention of
+// making zero values useful and gmp's decision not to.
+func (z *Int) doinit() {
+       if z.init {
+               return
+       }
+       z.init = true
+       C.mpz_init(&z.i[0])
+}
+
+// Bytes returns z's representation as a big-endian byte array.
+func (z *Int) Bytes() []byte {
+       b := make([]byte, (z.Len()+7)/8)
+       n := C.size_t(len(b))
+       C.mpz_export(unsafe.Pointer(&b[0]), &n, 1, 1, 1, 0, &z.i[0])
+       return b[0:n]
+}
+
+// Len returns the length of z in bits.  0 is considered to have length 1.
+func (z *Int) Len() int {
+       z.doinit()
+       return int(C.mpz_sizeinbase(&z.i[0], 2))
+}
+
+// Set sets z = x and returns z.
+func (z *Int) Set(x *Int) *Int {
+       z.doinit()
+       C.mpz_set(&z.i[0], &x.i[0])
+       return z
+}
+
+// SetBytes interprets b as the bytes of a big-endian integer
+// and sets z to that value.
+func (z *Int) SetBytes(b []byte) *Int {
+       z.doinit()
+       if len(b) == 0 {
+               z.SetInt64(0)
+       } else {
+               C.mpz_import(&z.i[0], C.size_t(len(b)), 1, 1, 1, 0, unsafe.Pointer(&b[0]))
+       }
+       return z
+}
+
+// SetInt64 sets z = x and returns z.
+func (z *Int) SetInt64(x int64) *Int {
+       z.doinit()
+       // TODO(rsc): more work on 32-bit platforms
+       C.mpz_set_si(&z.i[0], C.long(x))
+       return z
+}
+
+// SetString interprets s as a number in the given base
+// and sets z to that value.  The base must be in the range [2,36].
+// SetString returns an error if s cannot be parsed or the base is invalid.
+func (z *Int) SetString(s string, base int) error {
+       z.doinit()
+       if base < 2 || base > 36 {
+               return os.ErrInvalid
+       }
+       p := C.CString(s)
+       defer C.free(unsafe.Pointer(p))
+       if C.mpz_set_str(&z.i[0], p, C.int(base)) < 0 {
+               return os.ErrInvalid
+       }
+       return nil
+}
+
+// String returns the decimal representation of z.
+func (z *Int) String() string {
+       if z == nil {
+               return "nil"
+       }
+       z.doinit()
+       p := C.mpz_get_str(nil, 10, &z.i[0])
+       s := C.GoString(p)
+       C.free(unsafe.Pointer(p))
+       return s
+}
+
+func (z *Int) destroy() {
+       if z.init {
+               C.mpz_clear(&z.i[0])
+       }
+       z.init = false
+}
+
+/*
+ * arithmetic
+ */
+
+// Add sets z = x + y and returns z.
+func (z *Int) Add(x, y *Int) *Int {
+       x.doinit()
+       y.doinit()
+       z.doinit()
+       C.mpz_add(&z.i[0], &x.i[0], &y.i[0])
+       return z
+}
+
+// Sub sets z = x - y and returns z.
+func (z *Int) Sub(x, y *Int) *Int {
+       x.doinit()
+       y.doinit()
+       z.doinit()
+       C.mpz_sub(&z.i[0], &x.i[0], &y.i[0])
+       return z
+}
+
+// Mul sets z = x * y and returns z.
+func (z *Int) Mul(x, y *Int) *Int {
+       x.doinit()
+       y.doinit()
+       z.doinit()
+       C.mpz_mul(&z.i[0], &x.i[0], &y.i[0])
+       return z
+}
+
+// Div sets z = x / y, rounding toward zero, and returns z.
+func (z *Int) Div(x, y *Int) *Int {
+       x.doinit()
+       y.doinit()
+       z.doinit()
+       C.mpz_tdiv_q(&z.i[0], &x.i[0], &y.i[0])
+       return z
+}
+
+// Mod sets z = x % y and returns z.
+// Like the result of the Go % operator, z has the same sign as x.
+func (z *Int) Mod(x, y *Int) *Int {
+       x.doinit()
+       y.doinit()
+       z.doinit()
+       C.mpz_tdiv_r(&z.i[0], &x.i[0], &y.i[0])
+       return z
+}
+
+// Lsh sets z = x << s and returns z.
+func (z *Int) Lsh(x *Int, s uint) *Int {
+       x.doinit()
+       z.doinit()
+       C._mpz_mul_2exp(&z.i[0], &x.i[0], C.ulong(s))
+       return z
+}
+
+// Rsh sets z = x >> s and returns z.
+func (z *Int) Rsh(x *Int, s uint) *Int {
+       x.doinit()
+       z.doinit()
+       C._mpz_div_2exp(&z.i[0], &x.i[0], C.ulong(s))
+       return z
+}
+
+// Exp sets z = x^y % m and returns z.
+// If m == nil, Exp sets z = x^y.
+func (z *Int) Exp(x, y, m *Int) *Int {
+       m.doinit()
+       x.doinit()
+       y.doinit()
+       z.doinit()
+       if m == nil {
+               C.mpz_pow_ui(&z.i[0], &x.i[0], C.mpz_get_ui(&y.i[0]))
+       } else {
+               C.mpz_powm(&z.i[0], &x.i[0], &y.i[0], &m.i[0])
+       }
+       return z
+}
+
+func (z *Int) Int64() int64 {
+       if !z.init {
+               return 0
+       }
+       return int64(C.mpz_get_si(&z.i[0]))
+}
+
+// Neg sets z = -x and returns z.
+func (z *Int) Neg(x *Int) *Int {
+       x.doinit()
+       z.doinit()
+       C.mpz_neg(&z.i[0], &x.i[0])
+       return z
+}
+
+// Abs sets z to the absolute value of x and returns z.
+func (z *Int) Abs(x *Int) *Int {
+       x.doinit()
+       z.doinit()
+       C.mpz_abs(&z.i[0], &x.i[0])
+       return z
+}
+
+/*
+ * functions without a clear receiver
+ */
+
+// CmpInt compares x and y. The result is
+//
+//   -1 if x <  y
+//    0 if x == y
+//   +1 if x >  y
+//
+func CmpInt(x, y *Int) int {
+       x.doinit()
+       y.doinit()
+       switch cmp := C.mpz_cmp(&x.i[0], &y.i[0]); {
+       case cmp < 0:
+               return -1
+       case cmp == 0:
+               return 0
+       }
+       return +1
+}
+
+// DivModInt sets q = x / y and r = x % y.
+func DivModInt(q, r, x, y *Int) {
+       q.doinit()
+       r.doinit()
+       x.doinit()
+       y.doinit()
+       C.mpz_tdiv_qr(&q.i[0], &r.i[0], &x.i[0], &y.i[0])
+}
+
+// GcdInt sets d to the greatest common divisor of a and b,
+// which must be positive numbers.
+// If x and y are not nil, GcdInt sets x and y such that d = a*x + b*y.
+// If either a or b is not positive, GcdInt sets d = x = y = 0.
+func GcdInt(d, x, y, a, b *Int) {
+       d.doinit()
+       x.doinit()
+       y.doinit()
+       a.doinit()
+       b.doinit()
+       C.mpz_gcdext(&d.i[0], &x.i[0], &y.i[0], &a.i[0], &b.i[0])
+}
+
+// ProbablyPrime performs n Miller-Rabin tests to check whether z is prime.
+// If it returns true, z is prime with probability 1 - 1/4^n.
+// If it returns false, z is not prime.
+func (z *Int) ProbablyPrime(n int) bool {
+       z.doinit()
+       return int(C.mpz_probab_prime_p(&z.i[0], C.int(n))) > 0
+}
diff --git a/libgo/misc/cgo/gmp/pi.go b/libgo/misc/cgo/gmp/pi.go
new file mode 100644 (file)
index 0000000..d5851e8
--- /dev/null
@@ -0,0 +1,73 @@
+// Copyright 2009 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 ignore
+
+package main
+
+import (
+       big "."
+       "fmt"
+       "runtime"
+)
+
+var (
+       tmp1  = big.NewInt(0)
+       tmp2  = big.NewInt(0)
+       numer = big.NewInt(1)
+       accum = big.NewInt(0)
+       denom = big.NewInt(1)
+       ten   = big.NewInt(10)
+)
+
+func extractDigit() int64 {
+       if big.CmpInt(numer, accum) > 0 {
+               return -1
+       }
+       tmp1.Lsh(numer, 1).Add(tmp1, numer).Add(tmp1, accum)
+       big.DivModInt(tmp1, tmp2, tmp1, denom)
+       tmp2.Add(tmp2, numer)
+       if big.CmpInt(tmp2, denom) >= 0 {
+               return -1
+       }
+       return tmp1.Int64()
+}
+
+func nextTerm(k int64) {
+       y2 := k*2 + 1
+       accum.Add(accum, tmp1.Lsh(numer, 1))
+       accum.Mul(accum, tmp1.SetInt64(y2))
+       numer.Mul(numer, tmp1.SetInt64(k))
+       denom.Mul(denom, tmp1.SetInt64(y2))
+}
+
+func eliminateDigit(d int64) {
+       accum.Sub(accum, tmp1.Mul(denom, tmp1.SetInt64(d)))
+       accum.Mul(accum, ten)
+       numer.Mul(numer, ten)
+}
+
+func main() {
+       i := 0
+       k := int64(0)
+       for {
+               d := int64(-1)
+               for d < 0 {
+                       k++
+                       nextTerm(k)
+                       d = extractDigit()
+               }
+               eliminateDigit(d)
+               fmt.Printf("%c", d+'0')
+
+               if i++; i%50 == 0 {
+                       fmt.Printf("\n")
+                       if i >= 1000 {
+                               break
+                       }
+               }
+       }
+
+       fmt.Printf("\n%d calls; bit sizes: %d %d %d\n", runtime.NumCgoCall(), numer.Len(), accum.Len(), denom.Len())
+}
diff --git a/libgo/misc/cgo/life/c-life.c b/libgo/misc/cgo/life/c-life.c
new file mode 100644 (file)
index 0000000..f853163
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright 2010 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.
+
+#include <assert.h>
+#include "life.h"
+#include "_cgo_export.h"
+
+const int MYCONST = 0;
+
+// Do the actual manipulation of the life board in C.  This could be
+// done easily in Go, we are just using C for demonstration
+// purposes.
+void
+Step(int x, int y, int *a, int *n)
+{
+       struct GoStart_return r;
+
+       // Use Go to start 4 goroutines each of which handles 1/4 of the
+       // board.
+       r = GoStart(0, x, y, 0, x / 2, 0, y / 2, a, n);
+       assert(r.r0 == 0 && r.r1 == 100);       // test multiple returns
+       r = GoStart(1, x, y, x / 2, x, 0, y / 2, a, n);
+       assert(r.r0 == 1 && r.r1 == 101);       // test multiple returns
+       GoStart(2, x, y, 0, x / 2, y / 2, y, a, n);
+       GoStart(3, x, y, x / 2, x, y / 2, y, a, n);
+       GoWait(0);
+       GoWait(1);
+       GoWait(2);
+       GoWait(3);
+}
+
+// The actual computation.  This is called in parallel.
+void
+DoStep(int xdim, int ydim, int xstart, int xend, int ystart, int yend, int *a, int *n)
+{
+       int x, y, c, i, j;
+
+       for(x = xstart; x < xend; x++) {
+               for(y = ystart; y < yend; y++) {
+                       c = 0;
+                       for(i = -1; i <= 1; i++) {
+                               for(j = -1; j <= 1; j++) {
+                                 if(x+i >= 0 && x+i < xdim &&
+                                       y+j >= 0 && y+j < ydim &&
+                                       (i != 0 || j != 0))
+                                   c += a[(x+i)*xdim + (y+j)] != 0;
+                               }
+                       }
+                       if(c == 3 || (c == 2 && a[x*xdim + y] != 0))
+                               n[x*xdim + y] = 1;
+                       else
+                               n[x*xdim + y] = 0;
+               }
+       }
+}
diff --git a/libgo/misc/cgo/life/life.go b/libgo/misc/cgo/life/life.go
new file mode 100644 (file)
index 0000000..170a620
--- /dev/null
@@ -0,0 +1,41 @@
+// skip
+
+// Copyright 2010 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.
+
+package life
+
+// #include "life.h"
+import "C"
+
+import "unsafe"
+
+func Run(gen, x, y int, a []int32) {
+       n := make([]int32, x*y)
+       for i := 0; i < gen; i++ {
+               C.Step(C.int(x), C.int(y), (*C.int)(unsafe.Pointer(&a[0])), (*C.int)(unsafe.Pointer(&n[0])))
+               copy(a, n)
+       }
+}
+
+// Keep the channels visible from Go.
+var chans [4]chan bool
+
+//export GoStart
+// Double return value is just for testing.
+func GoStart(i, xdim, ydim, xstart, xend, ystart, yend C.int, a *C.int, n *C.int) (int, int) {
+       c := make(chan bool, int(C.MYCONST))
+       go func() {
+               C.DoStep(xdim, ydim, xstart, xend, ystart, yend, a, n)
+               c <- true
+       }()
+       chans[i] = c
+       return int(i), int(i + 100)
+}
+
+//export GoWait
+func GoWait(i C.int) {
+       <-chans[i]
+       chans[i] = nil
+}
diff --git a/libgo/misc/cgo/life/life.h b/libgo/misc/cgo/life/life.h
new file mode 100644 (file)
index 0000000..11d2b97
--- /dev/null
@@ -0,0 +1,7 @@
+// Copyright 2010 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.
+
+extern void Step(int, int, int *, int *);
+extern void DoStep(int, int, int, int, int, int, int *, int *);
+extern const int MYCONST;
diff --git a/libgo/misc/cgo/life/main.go b/libgo/misc/cgo/life/main.go
new file mode 100644 (file)
index 0000000..aa2f6d1
--- /dev/null
@@ -0,0 +1,48 @@
+// cmpout
+
+// Copyright 2010 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 test_run
+
+// Run the game of life in C using Go for parallelization.
+
+package main
+
+import (
+       "."
+       "flag"
+       "fmt"
+)
+
+const MAXDIM = 100
+
+var dim = flag.Int("dim", 16, "board dimensions")
+var gen = flag.Int("gen", 10, "generations")
+
+func main() {
+       flag.Parse()
+
+       var a [MAXDIM * MAXDIM]int32
+       for i := 2; i < *dim; i += 8 {
+               for j := 2; j < *dim-3; j += 8 {
+                       for y := 0; y < 3; y++ {
+                               a[i**dim+j+y] = 1
+                       }
+               }
+       }
+
+       life.Run(*gen, *dim, *dim, a[:])
+
+       for i := 0; i < *dim; i++ {
+               for j := 0; j < *dim; j++ {
+                       if a[i**dim+j] == 0 {
+                               fmt.Print(" ")
+                       } else {
+                               fmt.Print("X")
+                       }
+               }
+               fmt.Print("\n")
+       }
+}
diff --git a/libgo/misc/cgo/life/main.out b/libgo/misc/cgo/life/main.out
new file mode 100644 (file)
index 0000000..26fc9c6
--- /dev/null
@@ -0,0 +1,16 @@
+                
+                
+  XXX     XXX   
+                
+                
+                
+                
+                
+                
+                
+  XXX     XXX   
+                
+                
+                
+                
+                
diff --git a/libgo/misc/cgo/nocgo/nocgo.go b/libgo/misc/cgo/nocgo/nocgo.go
new file mode 100644 (file)
index 0000000..00ae5e9
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2014 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.
+
+// Test that -static works when not using cgo.  This test is in
+// misc/cgo to take advantage of the testing framework support for
+// when -static is expected to work.
+
+package nocgo
+
+func NoCgo() int {
+       c := make(chan int)
+
+       // The test is run with external linking, which means that
+       // goroutines will be created via the runtime/cgo package.
+       // Make sure that works.
+       go func() {
+               c <- 42
+       }()
+
+       return <-c
+}
diff --git a/libgo/misc/cgo/nocgo/nocgo_test.go b/libgo/misc/cgo/nocgo/nocgo_test.go
new file mode 100644 (file)
index 0000000..45d247c
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2014 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.
+
+package nocgo
+
+import "testing"
+
+func TestNop(t *testing.T) {
+       i := NoCgo()
+       if i != 42 {
+               t.Errorf("got %d, want %d", i, 42)
+       }
+}
diff --git a/libgo/misc/cgo/stdio/chain.go b/libgo/misc/cgo/stdio/chain.go
new file mode 100644 (file)
index 0000000..03cddb7
--- /dev/null
@@ -0,0 +1,48 @@
+// cmpout
+
+// Copyright 2009 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 test_run
+
+// Pass numbers along a chain of threads.
+
+package main
+
+import (
+       "runtime"
+       "strconv"
+
+       "../stdio"
+)
+
+const N = 10
+const R = 5
+
+func link(left chan<- int, right <-chan int) {
+       // Keep the links in dedicated operating system
+       // threads, so that this program tests coordination
+       // between pthreads and not just goroutines.
+       runtime.LockOSThread()
+       for {
+               v := <-right
+               stdio.Stdout.WriteString(strconv.Itoa(v) + "\n")
+               left <- 1 + v
+       }
+}
+
+func main() {
+       leftmost := make(chan int)
+       var left chan int
+       right := leftmost
+       for i := 0; i < N; i++ {
+               left, right = right, make(chan int)
+               go link(left, right)
+       }
+       for i := 0; i < R; i++ {
+               right <- 0
+               x := <-leftmost
+               stdio.Stdout.WriteString(strconv.Itoa(x) + "\n")
+       }
+}
diff --git a/libgo/misc/cgo/stdio/chain.out b/libgo/misc/cgo/stdio/chain.out
new file mode 100644 (file)
index 0000000..963cf9b
--- /dev/null
@@ -0,0 +1,55 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
diff --git a/libgo/misc/cgo/stdio/fib.go b/libgo/misc/cgo/stdio/fib.go
new file mode 100644 (file)
index 0000000..61a1b83
--- /dev/null
@@ -0,0 +1,52 @@
+// cmpout
+
+// Copyright 2009 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 test_run
+
+// Compute Fibonacci numbers with two goroutines
+// that pass integers back and forth.  No actual
+// concurrency, just threads and synchronization
+// and foreign code on multiple pthreads.
+
+package main
+
+import (
+       "runtime"
+       "strconv"
+
+       "../stdio"
+)
+
+func fibber(c, out chan int64, i int64) {
+       // Keep the fibbers in dedicated operating system
+       // threads, so that this program tests coordination
+       // between pthreads and not just goroutines.
+       runtime.LockOSThread()
+
+       if i == 0 {
+               c <- i
+       }
+       for {
+               j := <-c
+               stdio.Stdout.WriteString(strconv.FormatInt(j, 10) + "\n")
+               out <- j
+               <-out
+               i += j
+               c <- i
+       }
+}
+
+func main() {
+       c := make(chan int64)
+       out := make(chan int64)
+       go fibber(c, out, 0)
+       go fibber(c, out, 1)
+       <-out
+       for i := 0; i < 90; i++ {
+               out <- 1
+               <-out
+       }
+}
diff --git a/libgo/misc/cgo/stdio/fib.out b/libgo/misc/cgo/stdio/fib.out
new file mode 100644 (file)
index 0000000..17ff503
--- /dev/null
@@ -0,0 +1,91 @@
+0
+1
+1
+2
+3
+5
+8
+13
+21
+34
+55
+89
+144
+233
+377
+610
+987
+1597
+2584
+4181
+6765
+10946
+17711
+28657
+46368
+75025
+121393
+196418
+317811
+514229
+832040
+1346269
+2178309
+3524578
+5702887
+9227465
+14930352
+24157817
+39088169
+63245986
+102334155
+165580141
+267914296
+433494437
+701408733
+1134903170
+1836311903
+2971215073
+4807526976
+7778742049
+12586269025
+20365011074
+32951280099
+53316291173
+86267571272
+139583862445
+225851433717
+365435296162
+591286729879
+956722026041
+1548008755920
+2504730781961
+4052739537881
+6557470319842
+10610209857723
+17167680177565
+27777890035288
+44945570212853
+72723460248141
+117669030460994
+190392490709135
+308061521170129
+498454011879264
+806515533049393
+1304969544928657
+2111485077978050
+3416454622906707
+5527939700884757
+8944394323791464
+14472334024676221
+23416728348467685
+37889062373143906
+61305790721611591
+99194853094755497
+160500643816367088
+259695496911122585
+420196140727489673
+679891637638612258
+1100087778366101931
+1779979416004714189
+2880067194370816120
diff --git a/libgo/misc/cgo/stdio/file.go b/libgo/misc/cgo/stdio/file.go
new file mode 100644 (file)
index 0000000..a024f2c
--- /dev/null
@@ -0,0 +1,44 @@
+// skip
+
+// Copyright 2009 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.
+
+/*
+A trivial example of wrapping a C library in Go.
+For a more complex example and explanation,
+see ../gmp/gmp.go.
+*/
+
+package stdio
+
+/*
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+char* greeting = "hello, world";
+*/
+import "C"
+import "unsafe"
+
+type File C.FILE
+
+// Test reference to library symbol.
+// Stdout and stderr are too special to be a reliable test.
+//var  = C.environ
+
+func (f *File) WriteString(s string) {
+       p := C.CString(s)
+       C.fputs(p, (*C.FILE)(f))
+       C.free(unsafe.Pointer(p))
+       f.Flush()
+}
+
+func (f *File) Flush() {
+       C.fflush((*C.FILE)(f))
+}
+
+var Greeting = C.GoString(C.greeting)
+var Gbytes = C.GoBytes(unsafe.Pointer(C.greeting), C.int(len(Greeting)))
diff --git a/libgo/misc/cgo/stdio/hello.go b/libgo/misc/cgo/stdio/hello.go
new file mode 100644 (file)
index 0000000..47179ba
--- /dev/null
@@ -0,0 +1,15 @@
+// cmpout
+
+// Copyright 2009 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 test_run
+
+package main
+
+import "../stdio"
+
+func main() {
+       stdio.Stdout.WriteString(stdio.Greeting + "\n")
+}
diff --git a/libgo/misc/cgo/stdio/hello.out b/libgo/misc/cgo/stdio/hello.out
new file mode 100644 (file)
index 0000000..4b5fa63
--- /dev/null
@@ -0,0 +1 @@
+hello, world
diff --git a/libgo/misc/cgo/stdio/run.out b/libgo/misc/cgo/stdio/run.out
new file mode 100644 (file)
index 0000000..c0e4965
--- /dev/null
@@ -0,0 +1,150 @@
+* hello
+hello, world
+* fib
+0
+1
+1
+2
+3
+5
+8
+13
+21
+34
+55
+89
+144
+233
+377
+610
+987
+1597
+2584
+4181
+6765
+10946
+17711
+28657
+46368
+75025
+121393
+196418
+317811
+514229
+832040
+1346269
+2178309
+3524578
+5702887
+9227465
+14930352
+24157817
+39088169
+63245986
+102334155
+165580141
+267914296
+433494437
+701408733
+1134903170
+1836311903
+2971215073
+4807526976
+7778742049
+12586269025
+20365011074
+32951280099
+53316291173
+86267571272
+139583862445
+225851433717
+365435296162
+591286729879
+956722026041
+1548008755920
+2504730781961
+4052739537881
+6557470319842
+10610209857723
+17167680177565
+27777890035288
+44945570212853
+72723460248141
+117669030460994
+190392490709135
+308061521170129
+498454011879264
+806515533049393
+1304969544928657
+2111485077978050
+3416454622906707
+5527939700884757
+8944394323791464
+14472334024676221
+23416728348467685
+37889062373143906
+61305790721611591
+99194853094755497
+160500643816367088
+259695496911122585
+420196140727489673
+679891637638612258
+1100087778366101931
+1779979416004714189
+2880067194370816120
+* chain
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
diff --git a/libgo/misc/cgo/stdio/stdio.go b/libgo/misc/cgo/stdio/stdio.go
new file mode 100644 (file)
index 0000000..d216e44
--- /dev/null
@@ -0,0 +1,22 @@
+// skip
+
+// Copyright 2009 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.
+
+package stdio
+
+/*
+#include <stdio.h>
+
+// on mingw, stderr and stdout are defined as &_iob[FILENO]
+// on netbsd, they are defined as &__sF[FILENO]
+// and cgo doesn't recognize them, so write a function to get them,
+// instead of depending on internals of libc implementation.
+FILE *getStdout(void) { return stdout; }
+FILE *getStderr(void) { return stderr; }
+*/
+import "C"
+
+var Stdout = (*File)(C.getStdout())
+var Stderr = (*File)(C.getStderr())
diff --git a/libgo/misc/cgo/test/align.go b/libgo/misc/cgo/test/align.go
new file mode 100644 (file)
index 0000000..a23b44f
--- /dev/null
@@ -0,0 +1,76 @@
+// Copyright 2010 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.
+
+package cgotest
+
+/*
+#include <stdio.h>
+
+typedef unsigned char Uint8;
+typedef unsigned short Uint16;
+
+typedef enum {
+ MOD1 = 0x0000,
+ MODX = 0x8000
+} SDLMod;
+
+typedef enum {
+ A = 1,
+ B = 322,
+ SDLK_LAST
+} SDLKey;
+
+typedef struct SDL_keysym {
+       Uint8 scancode;
+       SDLKey sym;
+       SDLMod mod;
+       Uint16 unicode;
+} SDL_keysym;
+
+typedef struct SDL_KeyboardEvent {
+       Uint8 typ;
+       Uint8 which;
+       Uint8 state;
+       SDL_keysym keysym;
+} SDL_KeyboardEvent;
+
+void makeEvent(SDL_KeyboardEvent *event) {
+ unsigned char *p;
+ int i;
+
+ p = (unsigned char*)event;
+ for (i=0; i<sizeof *event; i++) {
+   p[i] = i;
+ }
+}
+
+int same(SDL_KeyboardEvent* e, Uint8 typ, Uint8 which, Uint8 state, Uint8 scan, SDLKey sym, SDLMod mod, Uint16 uni) {
+  return e->typ == typ && e->which == which && e->state == state && e->keysym.scancode == scan && e->keysym.sym == sym && e->keysym.mod == mod && e->keysym.unicode == uni;
+}
+
+void cTest(SDL_KeyboardEvent *event) {
+ printf("C: %#x %#x %#x %#x %#x %#x %#x\n", event->typ, event->which, event->state,
+   event->keysym.scancode, event->keysym.sym, event->keysym.mod, event->keysym.unicode);
+ fflush(stdout);
+}
+
+*/
+import "C"
+
+import (
+       "testing"
+)
+
+func testAlign(t *testing.T) {
+       var evt C.SDL_KeyboardEvent
+       C.makeEvent(&evt)
+       if C.same(&evt, evt.typ, evt.which, evt.state, evt.keysym.scancode, evt.keysym.sym, evt.keysym.mod, evt.keysym.unicode) == 0 {
+               t.Error("*** bad alignment")
+               C.cTest(&evt)
+               t.Errorf("Go: %#x %#x %#x %#x %#x %#x %#x\n",
+                       evt.typ, evt.which, evt.state, evt.keysym.scancode,
+                       evt.keysym.sym, evt.keysym.mod, evt.keysym.unicode)
+               t.Error(evt)
+       }
+}
diff --git a/libgo/misc/cgo/test/api.go b/libgo/misc/cgo/test/api.go
new file mode 100644 (file)
index 0000000..d2b09cb
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2013 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.
+
+// API Compatibility Checks for cgo
+
+package cgotest
+
+// #include <stdlib.h>
+//
+// // Test for issue 17723.
+// typedef char *cstring_pointer;
+// static void cstring_pointer_fun(cstring_pointer dummy) { }
+//
+// const char *api_hello = "hello!";
+import "C"
+import "unsafe"
+
+func testAPI() {
+       var cs *C.char
+       cs = C.CString("hello")
+       defer C.free(unsafe.Pointer(cs))
+       var s string
+       s = C.GoString((*C.char)(C.api_hello))
+       s = C.GoStringN((*C.char)(C.api_hello), C.int(6))
+       var b []byte
+       b = C.GoBytes(unsafe.Pointer(C.api_hello), C.int(6))
+       _, _ = s, b
+       C.cstring_pointer_fun(nil)
+}
diff --git a/libgo/misc/cgo/test/backdoor.go b/libgo/misc/cgo/test/backdoor.go
new file mode 100644 (file)
index 0000000..6fb33d6
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2014 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.
+
+package cgotest
+
+import _ "unsafe"
+
+//go:linkname lockedOSThread runtime.lockedOSThread
+//extern runtime_lockedOSThread
+func lockedOSThread() bool
diff --git a/libgo/misc/cgo/test/basic.go b/libgo/misc/cgo/test/basic.go
new file mode 100644 (file)
index 0000000..3ceb4ce
--- /dev/null
@@ -0,0 +1,167 @@
+// Copyright 2010 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.
+
+// Basic test cases for cgo.
+
+package cgotest
+
+/*
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#define SHIFT(x, y)  ((x)<<(y))
+#define KILO SHIFT(1, 10)
+#define UINT32VAL 0xc008427bU
+
+enum E {
+       Enum1 = 1,
+       Enum2 = 2,
+};
+
+typedef unsigned char cgo_uuid_t[20];
+
+void uuid_generate(cgo_uuid_t x) {
+       x[0] = 0;
+}
+
+struct S {
+       int x;
+};
+
+extern enum E myConstFunc(struct S* const ctx, int const id, struct S **const filter);
+
+enum E myConstFunc(struct S *const ctx, int const id, struct S **const filter) { return 0; }
+
+// issue 1222
+typedef union {
+       long align;
+} xxpthread_mutex_t;
+
+struct ibv_async_event {
+       union {
+               int x;
+       } element;
+};
+
+struct ibv_context {
+       xxpthread_mutex_t mutex;
+};
+
+int add(int x, int y) {
+       return x+y;
+};
+*/
+import "C"
+import (
+       "runtime"
+       "syscall"
+       "testing"
+       "unsafe"
+)
+
+const EINVAL = C.EINVAL /* test #define */
+
+var KILO = C.KILO
+
+func uuidgen() {
+       var uuid C.cgo_uuid_t
+       C.uuid_generate(&uuid[0])
+}
+
+func Strtol(s string, base int) (int, error) {
+       p := C.CString(s)
+       n, err := C.strtol(p, nil, C.int(base))
+       C.free(unsafe.Pointer(p))
+       return int(n), err
+}
+
+func Atol(s string) int {
+       p := C.CString(s)
+       n := C.atol(p)
+       C.free(unsafe.Pointer(p))
+       return int(n)
+}
+
+func testConst(t *testing.T) {
+       C.myConstFunc(nil, 0, nil)
+}
+
+func testEnum(t *testing.T) {
+       if C.Enum1 != 1 || C.Enum2 != 2 {
+               t.Error("bad enum", C.Enum1, C.Enum2)
+       }
+}
+
+func testAtol(t *testing.T) {
+       l := Atol("123")
+       if l != 123 {
+               t.Error("Atol 123: ", l)
+       }
+}
+
+func testErrno(t *testing.T) {
+       p := C.CString("no-such-file")
+       m := C.CString("r")
+       f, err := C.fopen(p, m)
+       C.free(unsafe.Pointer(p))
+       C.free(unsafe.Pointer(m))
+       if err == nil {
+               C.fclose(f)
+               t.Fatalf("C.fopen: should fail")
+       }
+       if err != syscall.ENOENT {
+               t.Fatalf("C.fopen: unexpected error: %v", err)
+       }
+}
+
+func testMultipleAssign(t *testing.T) {
+       p := C.CString("234")
+       n, m := C.strtol(p, nil, 345), C.strtol(p, nil, 10)
+       if runtime.GOOS == "openbsd" {
+               // Bug in OpenBSD strtol(3) - base > 36 succeeds.
+               if (n != 0 && n != 239089) || m != 234 {
+                       t.Fatal("Strtol x2: ", n, m)
+               }
+       } else if n != 0 || m != 234 {
+               t.Fatal("Strtol x2: ", n, m)
+       }
+       C.free(unsafe.Pointer(p))
+}
+
+var (
+       cuint  = (C.uint)(0)
+       culong C.ulong
+       cchar  C.char
+)
+
+type Context struct {
+       ctx *C.struct_ibv_context
+}
+
+func benchCgoCall(b *testing.B) {
+       const x = C.int(2)
+       const y = C.int(3)
+       for i := 0; i < b.N; i++ {
+               C.add(x, y)
+       }
+}
+
+// Issue 2470.
+func testUnsignedInt(t *testing.T) {
+       a := (int64)(C.UINT32VAL)
+       b := (int64)(0xc008427b)
+       if a != b {
+               t.Errorf("Incorrect unsigned int - got %x, want %x", a, b)
+       }
+}
+
+// Static (build-time) test that syntax traversal visits all operands of s[i:j:k].
+func sliceOperands(array [2000]int) {
+       _ = array[C.KILO:C.KILO:C.KILO] // no type error
+}
+
+// set in cgo_thread_lock.go init
+var testThreadLockFunc = func(*testing.T) {}
diff --git a/libgo/misc/cgo/test/buildid_linux.go b/libgo/misc/cgo/test/buildid_linux.go
new file mode 100644 (file)
index 0000000..47dd871
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright 2014 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.
+
+package cgotest
+
+// Test that we have no more than one build ID.  In the past we used
+// to generate a separate build ID for each package using cgo, and the
+// linker concatenated them all.  We don't want that--we only want
+// one.
+
+import (
+       "bytes"
+       "debug/elf"
+       "os"
+       "testing"
+)
+
+func testBuildID(t *testing.T) {
+       f, err := elf.Open("/proc/self/exe")
+       if err != nil {
+               if os.IsNotExist(err) {
+                       t.Skip("no /proc/self/exe")
+               }
+               t.Fatal("opening /proc/self/exe: ", err)
+       }
+       defer f.Close()
+
+       c := 0
+       for i, s := range f.Sections {
+               if s.Type != elf.SHT_NOTE {
+                       continue
+               }
+
+               d, err := s.Data()
+               if err != nil {
+                       t.Logf("reading data of note section %d: %v", i, err)
+                       continue
+               }
+
+               for len(d) > 0 {
+
+                       // ELF standards differ as to the sizes in
+                       // note sections.  Both the GNU linker and
+                       // gold always generate 32-bit sizes, so that
+                       // is what we assume here.
+
+                       if len(d) < 12 {
+                               t.Logf("note section %d too short (%d < 12)", i, len(d))
+                               continue
+                       }
+
+                       namesz := f.ByteOrder.Uint32(d)
+                       descsz := f.ByteOrder.Uint32(d[4:])
+                       typ := f.ByteOrder.Uint32(d[8:])
+
+                       an := (namesz + 3) &^ 3
+                       ad := (descsz + 3) &^ 3
+
+                       if int(12+an+ad) > len(d) {
+                               t.Logf("note section %d too short for header (%d < 12 + align(%d,4) + align(%d,4))", i, len(d), namesz, descsz)
+                               continue
+                       }
+
+                       // 3 == NT_GNU_BUILD_ID
+                       if typ == 3 && namesz == 4 && bytes.Equal(d[12:16], []byte("GNU\000")) {
+                               c++
+                       }
+
+                       d = d[12+an+ad:]
+               }
+       }
+
+       if c > 1 {
+               t.Errorf("found %d build ID notes", c)
+       }
+}
diff --git a/libgo/misc/cgo/test/callback.go b/libgo/misc/cgo/test/callback.go
new file mode 100644 (file)
index 0000000..b88bf13
--- /dev/null
@@ -0,0 +1,1782 @@
+// Copyright 2011 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.
+
+package cgotest
+
+/*
+void callback(void *f);
+void callGoFoo(void);
+void callGoStackCheck(void);
+void callPanic(void);
+int callGoReturnVal(void);
+int returnAfterGrow(void);
+int returnAfterGrowFromGo(void);
+void callGoWithString(void);
+*/
+import "C"
+
+import (
+       "path"
+       "runtime"
+       "strings"
+       "sync"
+       "testing"
+       "unsafe"
+)
+
+// Pass a func value from nestedCall to goCallback using an integer token.
+var callbackMutex sync.Mutex
+var callbackToken int
+var callbackFuncs = make(map[int]func())
+
+// nestedCall calls into C, back into Go, and finally to f.
+func nestedCall(f func()) {
+       // callback(x) calls goCallback(x)
+       callbackMutex.Lock()
+       callbackToken++
+       i := callbackToken
+       callbackFuncs[i] = f
+       callbackMutex.Unlock()
+
+       // Pass the address of i because the C function was written to
+       // take a pointer.  We could pass an int if we felt like
+       // rewriting the C code.
+       C.callback(unsafe.Pointer(&i))
+
+       callbackMutex.Lock()
+       delete(callbackFuncs, i)
+       callbackMutex.Unlock()
+}
+
+//export goCallback
+func goCallback(p unsafe.Pointer) {
+       i := *(*int)(p)
+
+       callbackMutex.Lock()
+       f := callbackFuncs[i]
+       callbackMutex.Unlock()
+
+       if f == nil {
+               panic("missing callback function")
+       }
+       f()
+}
+
+func testCallback(t *testing.T) {
+       var x = false
+       nestedCall(func() { x = true })
+       if !x {
+               t.Fatal("nestedCall did not call func")
+       }
+}
+
+func testCallbackGC(t *testing.T) {
+       nestedCall(runtime.GC)
+}
+
+func testCallbackPanic(t *testing.T) {
+       // Make sure panic during callback unwinds properly.
+       if lockedOSThread() {
+               t.Fatal("locked OS thread on entry to TestCallbackPanic")
+       }
+       defer func() {
+               s := recover()
+               if s == nil {
+                       t.Fatal("did not panic")
+               }
+               if s.(string) != "callback panic" {
+                       t.Fatal("wrong panic:", s)
+               }
+               if lockedOSThread() {
+                       t.Fatal("locked OS thread on exit from TestCallbackPanic")
+               }
+       }()
+       nestedCall(func() { panic("callback panic") })
+       panic("nestedCall returned")
+}
+
+func testCallbackPanicLoop(t *testing.T) {
+       // Make sure we don't blow out m->g0 stack.
+       for i := 0; i < 100000; i++ {
+               testCallbackPanic(t)
+       }
+}
+
+func testCallbackPanicLocked(t *testing.T) {
+       runtime.LockOSThread()
+       defer runtime.UnlockOSThread()
+
+       if !lockedOSThread() {
+               t.Fatal("runtime.LockOSThread didn't")
+       }
+       defer func() {
+               s := recover()
+               if s == nil {
+                       t.Fatal("did not panic")
+               }
+               if s.(string) != "callback panic" {
+                       t.Fatal("wrong panic:", s)
+               }
+               if !lockedOSThread() {
+                       t.Fatal("lost lock on OS thread after panic")
+               }
+       }()
+       nestedCall(func() { panic("callback panic") })
+       panic("nestedCall returned")
+}
+
+// Callback with zero arguments used to make the stack misaligned,
+// which broke the garbage collector and other things.
+func testZeroArgCallback(t *testing.T) {
+       defer func() {
+               s := recover()
+               if s != nil {
+                       t.Fatal("panic during callback:", s)
+               }
+       }()
+       C.callGoFoo()
+}
+
+//export goFoo
+func goFoo() {
+       x := 1
+       for i := 0; i < 10000; i++ {
+               // variadic call mallocs + writes to
+               variadic(x, x, x)
+               if x != 1 {
+                       panic("bad x")
+               }
+       }
+}
+
+func variadic(x ...interface{}) {}
+
+func testBlocking(t *testing.T) {
+       c := make(chan int)
+       go func() {
+               for i := 0; i < 10; i++ {
+                       c <- <-c
+               }
+       }()
+       nestedCall(func() {
+               for i := 0; i < 10; i++ {
+                       c <- i
+                       if j := <-c; j != i {
+                               t.Errorf("out of sync %d != %d", j, i)
+                       }
+               }
+       })
+}
+
+// Test that the stack can be unwound through a call out and call back
+// into Go.
+func testCallbackCallers(t *testing.T) {
+       if runtime.Compiler != "gc" {
+               // The exact function names are not going to be the same.
+               t.Skip("skipping for non-gc toolchain")
+       }
+       pc := make([]uintptr, 100)
+       n := 0
+       name := []string{
+               "runtime.call16",
+               "runtime.cgocallbackg1",
+               "runtime.cgocallbackg",
+               "runtime.cgocallback_gofunc",
+               "runtime.asmcgocall",
+               "runtime.cgocall",
+               "test._Cfunc_callback",
+               "test.nestedCall.func1",
+               "test.nestedCall",
+               "test.testCallbackCallers",
+               "test.TestCallbackCallers",
+               "testing.tRunner",
+               "runtime.goexit",
+       }
+       if unsafe.Sizeof((*byte)(nil)) == 8 {
+               name[0] = "runtime.call32"
+       }
+       nestedCall(func() {
+               n = runtime.Callers(4, pc)
+       })
+       if n != len(name) {
+               t.Errorf("expected %d frames, got %d", len(name), n)
+       }
+       for i := 0; i < n; i++ {
+               f := runtime.FuncForPC(pc[i])
+               if f == nil {
+                       t.Fatalf("expected non-nil Func for pc %d", pc[i])
+               }
+               fname := f.Name()
+               // Remove the prepended pathname from automatically
+               // generated cgo function names.
+               if strings.HasPrefix(fname, "_") {
+                       fname = path.Base(f.Name()[1:])
+               }
+               namei := ""
+               if i < len(name) {
+                       namei = name[i]
+               }
+               if fname != namei {
+                       t.Errorf("stk[%d] = %q, want %q", i, fname, namei)
+               }
+       }
+}
+
+func testPanicFromC(t *testing.T) {
+       defer func() {
+               r := recover()
+               if r == nil {
+                       t.Fatal("did not panic")
+               }
+               if r.(string) != "panic from C" {
+                       t.Fatal("wrong panic:", r)
+               }
+       }()
+       C.callPanic()
+}
+
+// Test that C code can return a value if it calls a Go function that
+// causes a stack copy.
+func testReturnAfterGrow(t *testing.T) {
+       // Use a new goroutine so that we get a small stack.
+       c := make(chan int)
+       go func() {
+               c <- int(C.returnAfterGrow())
+       }()
+       if got, want := <-c, 123456; got != want {
+               t.Errorf("got %d want %d", got, want)
+       }
+}
+
+// Test that we can return a value from Go->C->Go if the Go code
+// causes a stack copy.
+func testReturnAfterGrowFromGo(t *testing.T) {
+       // Use a new goroutine so that we get a small stack.
+       c := make(chan int)
+       go func() {
+               c <- int(C.returnAfterGrowFromGo())
+       }()
+       if got, want := <-c, 129*128/2; got != want {
+               t.Errorf("got %d want %d", got, want)
+       }
+}
+
+//export goReturnVal
+func goReturnVal() (r C.int) {
+       // Force a stack copy.
+       var f func(int) int
+       f = func(i int) int {
+               var buf [256]byte
+               use(buf[:])
+               if i == 0 {
+                       return 0
+               }
+               return i + f(i-1)
+       }
+       r = C.int(f(128))
+       return
+}
+
+// Test that C can pass in a Go string from a string constant.
+func testCallGoWithString(t *testing.T) {
+       C.callGoWithString()
+       want := "string passed from C to Go"
+       if stringFromGo != want {
+               t.Errorf("string passed through C is %s, want %s", stringFromGo, want)
+       }
+}
+
+var stringFromGo string
+
+//export goWithString
+func goWithString(s string) {
+       stringFromGo = s
+}
+
+func testCallbackStack(t *testing.T) {
+       // Make cgo call and callback with different amount of stack stack available.
+       // We do not do any explicit checks, just ensure that it does not crash.
+       for _, f := range splitTests {
+               f()
+       }
+}
+
+//export goStackCheck
+func goStackCheck() {
+       // use some stack memory to trigger split stack check
+       var buf [256]byte
+       use(buf[:])
+}
+
+var Used byte
+
+func use(buf []byte) {
+       for _, c := range buf {
+               Used += c
+       }
+}
+
+var splitTests = []func(){
+       // Edit .+1,/^}/-1|seq 4 4 5000 | sed 's/.*/    stack&,/' | fmt
+       stack4, stack8, stack12, stack16, stack20, stack24, stack28,
+       stack32, stack36, stack40, stack44, stack48, stack52, stack56,
+       stack60, stack64, stack68, stack72, stack76, stack80, stack84,
+       stack88, stack92, stack96, stack100, stack104, stack108, stack112,
+       stack116, stack120, stack124, stack128, stack132, stack136,
+       stack140, stack144, stack148, stack152, stack156, stack160,
+       stack164, stack168, stack172, stack176, stack180, stack184,
+       stack188, stack192, stack196, stack200, stack204, stack208,
+       stack212, stack216, stack220, stack224, stack228, stack232,
+       stack236, stack240, stack244, stack248, stack252, stack256,
+       stack260, stack264, stack268, stack272, stack276, stack280,
+       stack284, stack288, stack292, stack296, stack300, stack304,
+       stack308, stack312, stack316, stack320, stack324, stack328,
+       stack332, stack336, stack340, stack344, stack348, stack352,
+       stack356, stack360, stack364, stack368, stack372, stack376,
+       stack380, stack384, stack388, stack392, stack396, stack400,
+       stack404, stack408, stack412, stack416, stack420, stack424,
+       stack428, stack432, stack436, stack440, stack444, stack448,
+       stack452, stack456, stack460, stack464, stack468, stack472,
+       stack476, stack480, stack484, stack488, stack492, stack496,
+       stack500, stack504, stack508, stack512, stack516, stack520,
+       stack524, stack528, stack532, stack536, stack540, stack544,
+       stack548, stack552, stack556, stack560, stack564, stack568,
+       stack572, stack576, stack580, stack584, stack588, stack592,
+       stack596, stack600, stack604, stack608, stack612, stack616,
+       stack620, stack624, stack628, stack632, stack636, stack640,
+       stack644, stack648, stack652, stack656, stack660, stack664,
+       stack668, stack672, stack676, stack680, stack684, stack688,
+       stack692, stack696, stack700, stack704, stack708, stack712,
+       stack716, stack720, stack724, stack728, stack732, stack736,
+       stack740, stack744, stack748, stack752, stack756, stack760,
+       stack764, stack768, stack772, stack776, stack780, stack784,
+       stack788, stack792, stack796, stack800, stack804, stack808,
+       stack812, stack816, stack820, stack824, stack828, stack832,
+       stack836, stack840, stack844, stack848, stack852, stack856,
+       stack860, stack864, stack868, stack872, stack876, stack880,
+       stack884, stack888, stack892, stack896, stack900, stack904,
+       stack908, stack912, stack916, stack920, stack924, stack928,
+       stack932, stack936, stack940, stack944, stack948, stack952,
+       stack956, stack960, stack964, stack968, stack972, stack976,
+       stack980, stack984, stack988, stack992, stack996, stack1000,
+       stack1004, stack1008, stack1012, stack1016, stack1020, stack1024,
+       stack1028, stack1032, stack1036, stack1040, stack1044, stack1048,
+       stack1052, stack1056, stack1060, stack1064, stack1068, stack1072,
+       stack1076, stack1080, stack1084, stack1088, stack1092, stack1096,
+       stack1100, stack1104, stack1108, stack1112, stack1116, stack1120,
+       stack1124, stack1128, stack1132, stack1136, stack1140, stack1144,
+       stack1148, stack1152, stack1156, stack1160, stack1164, stack1168,
+       stack1172, stack1176, stack1180, stack1184, stack1188, stack1192,
+       stack1196, stack1200, stack1204, stack1208, stack1212, stack1216,
+       stack1220, stack1224, stack1228, stack1232, stack1236, stack1240,
+       stack1244, stack1248, stack1252, stack1256, stack1260, stack1264,
+       stack1268, stack1272, stack1276, stack1280, stack1284, stack1288,
+       stack1292, stack1296, stack1300, stack1304, stack1308, stack1312,
+       stack1316, stack1320, stack1324, stack1328, stack1332, stack1336,
+       stack1340, stack1344, stack1348, stack1352, stack1356, stack1360,
+       stack1364, stack1368, stack1372, stack1376, stack1380, stack1384,
+       stack1388, stack1392, stack1396, stack1400, stack1404, stack1408,
+       stack1412, stack1416, stack1420, stack1424, stack1428, stack1432,
+       stack1436, stack1440, stack1444, stack1448, stack1452, stack1456,
+       stack1460, stack1464, stack1468, stack1472, stack1476, stack1480,
+       stack1484, stack1488, stack1492, stack1496, stack1500, stack1504,
+       stack1508, stack1512, stack1516, stack1520, stack1524, stack1528,
+       stack1532, stack1536, stack1540, stack1544, stack1548, stack1552,
+       stack1556, stack1560, stack1564, stack1568, stack1572, stack1576,
+       stack1580, stack1584, stack1588, stack1592, stack1596, stack1600,
+       stack1604, stack1608, stack1612, stack1616, stack1620, stack1624,
+       stack1628, stack1632, stack1636, stack1640, stack1644, stack1648,
+       stack1652, stack1656, stack1660, stack1664, stack1668, stack1672,
+       stack1676, stack1680, stack1684, stack1688, stack1692, stack1696,
+       stack1700, stack1704, stack1708, stack1712, stack1716, stack1720,
+       stack1724, stack1728, stack1732, stack1736, stack1740, stack1744,
+       stack1748, stack1752, stack1756, stack1760, stack1764, stack1768,
+       stack1772, stack1776, stack1780, stack1784, stack1788, stack1792,
+       stack1796, stack1800, stack1804, stack1808, stack1812, stack1816,
+       stack1820, stack1824, stack1828, stack1832, stack1836, stack1840,
+       stack1844, stack1848, stack1852, stack1856, stack1860, stack1864,
+       stack1868, stack1872, stack1876, stack1880, stack1884, stack1888,
+       stack1892, stack1896, stack1900, stack1904, stack1908, stack1912,
+       stack1916, stack1920, stack1924, stack1928, stack1932, stack1936,
+       stack1940, stack1944, stack1948, stack1952, stack1956, stack1960,
+       stack1964, stack1968, stack1972, stack1976, stack1980, stack1984,
+       stack1988, stack1992, stack1996, stack2000, stack2004, stack2008,
+       stack2012, stack2016, stack2020, stack2024, stack2028, stack2032,
+       stack2036, stack2040, stack2044, stack2048, stack2052, stack2056,
+       stack2060, stack2064, stack2068, stack2072, stack2076, stack2080,
+       stack2084, stack2088, stack2092, stack2096, stack2100, stack2104,
+       stack2108, stack2112, stack2116, stack2120, stack2124, stack2128,
+       stack2132, stack2136, stack2140, stack2144, stack2148, stack2152,
+       stack2156, stack2160, stack2164, stack2168, stack2172, stack2176,
+       stack2180, stack2184, stack2188, stack2192, stack2196, stack2200,
+       stack2204, stack2208, stack2212, stack2216, stack2220, stack2224,
+       stack2228, stack2232, stack2236, stack2240, stack2244, stack2248,
+       stack2252, stack2256, stack2260, stack2264, stack2268, stack2272,
+       stack2276, stack2280, stack2284, stack2288, stack2292, stack2296,
+       stack2300, stack2304, stack2308, stack2312, stack2316, stack2320,
+       stack2324, stack2328, stack2332, stack2336, stack2340, stack2344,
+       stack2348, stack2352, stack2356, stack2360, stack2364, stack2368,
+       stack2372, stack2376, stack2380, stack2384, stack2388, stack2392,
+       stack2396, stack2400, stack2404, stack2408, stack2412, stack2416,
+       stack2420, stack2424, stack2428, stack2432, stack2436, stack2440,
+       stack2444, stack2448, stack2452, stack2456, stack2460, stack2464,
+       stack2468, stack2472, stack2476, stack2480, stack2484, stack2488,
+       stack2492, stack2496, stack2500, stack2504, stack2508, stack2512,
+       stack2516, stack2520, stack2524, stack2528, stack2532, stack2536,
+       stack2540, stack2544, stack2548, stack2552, stack2556, stack2560,
+       stack2564, stack2568, stack2572, stack2576, stack2580, stack2584,
+       stack2588, stack2592, stack2596, stack2600, stack2604, stack2608,
+       stack2612, stack2616, stack2620, stack2624, stack2628, stack2632,
+       stack2636, stack2640, stack2644, stack2648, stack2652, stack2656,
+       stack2660, stack2664, stack2668, stack2672, stack2676, stack2680,
+       stack2684, stack2688, stack2692, stack2696, stack2700, stack2704,
+       stack2708, stack2712, stack2716, stack2720, stack2724, stack2728,
+       stack2732, stack2736, stack2740, stack2744, stack2748, stack2752,
+       stack2756, stack2760, stack2764, stack2768, stack2772, stack2776,
+       stack2780, stack2784, stack2788, stack2792, stack2796, stack2800,
+       stack2804, stack2808, stack2812, stack2816, stack2820, stack2824,
+       stack2828, stack2832, stack2836, stack2840, stack2844, stack2848,
+       stack2852, stack2856, stack2860, stack2864, stack2868, stack2872,
+       stack2876, stack2880, stack2884, stack2888, stack2892, stack2896,
+       stack2900, stack2904, stack2908, stack2912, stack2916, stack2920,
+       stack2924, stack2928, stack2932, stack2936, stack2940, stack2944,
+       stack2948, stack2952, stack2956, stack2960, stack2964, stack2968,
+       stack2972, stack2976, stack2980, stack2984, stack2988, stack2992,
+       stack2996, stack3000, stack3004, stack3008, stack3012, stack3016,
+       stack3020, stack3024, stack3028, stack3032, stack3036, stack3040,
+       stack3044, stack3048, stack3052, stack3056, stack3060, stack3064,
+       stack3068, stack3072, stack3076, stack3080, stack3084, stack3088,
+       stack3092, stack3096, stack3100, stack3104, stack3108, stack3112,
+       stack3116, stack3120, stack3124, stack3128, stack3132, stack3136,
+       stack3140, stack3144, stack3148, stack3152, stack3156, stack3160,
+       stack3164, stack3168, stack3172, stack3176, stack3180, stack3184,
+       stack3188, stack3192, stack3196, stack3200, stack3204, stack3208,
+       stack3212, stack3216, stack3220, stack3224, stack3228, stack3232,
+       stack3236, stack3240, stack3244, stack3248, stack3252, stack3256,
+       stack3260, stack3264, stack3268, stack3272, stack3276, stack3280,
+       stack3284, stack3288, stack3292, stack3296, stack3300, stack3304,
+       stack3308, stack3312, stack3316, stack3320, stack3324, stack3328,
+       stack3332, stack3336, stack3340, stack3344, stack3348, stack3352,
+       stack3356, stack3360, stack3364, stack3368, stack3372, stack3376,
+       stack3380, stack3384, stack3388, stack3392, stack3396, stack3400,
+       stack3404, stack3408, stack3412, stack3416, stack3420, stack3424,
+       stack3428, stack3432, stack3436, stack3440, stack3444, stack3448,
+       stack3452, stack3456, stack3460, stack3464, stack3468, stack3472,
+       stack3476, stack3480, stack3484, stack3488, stack3492, stack3496,
+       stack3500, stack3504, stack3508, stack3512, stack3516, stack3520,
+       stack3524, stack3528, stack3532, stack3536, stack3540, stack3544,
+       stack3548, stack3552, stack3556, stack3560, stack3564, stack3568,
+       stack3572, stack3576, stack3580, stack3584, stack3588, stack3592,
+       stack3596, stack3600, stack3604, stack3608, stack3612, stack3616,
+       stack3620, stack3624, stack3628, stack3632, stack3636, stack3640,
+       stack3644, stack3648, stack3652, stack3656, stack3660, stack3664,
+       stack3668, stack3672, stack3676, stack3680, stack3684, stack3688,
+       stack3692, stack3696, stack3700, stack3704, stack3708, stack3712,
+       stack3716, stack3720, stack3724, stack3728, stack3732, stack3736,
+       stack3740, stack3744, stack3748, stack3752, stack3756, stack3760,
+       stack3764, stack3768, stack3772, stack3776, stack3780, stack3784,
+       stack3788, stack3792, stack3796, stack3800, stack3804, stack3808,
+       stack3812, stack3816, stack3820, stack3824, stack3828, stack3832,
+       stack3836, stack3840, stack3844, stack3848, stack3852, stack3856,
+       stack3860, stack3864, stack3868, stack3872, stack3876, stack3880,
+       stack3884, stack3888, stack3892, stack3896, stack3900, stack3904,
+       stack3908, stack3912, stack3916, stack3920, stack3924, stack3928,
+       stack3932, stack3936, stack3940, stack3944, stack3948, stack3952,
+       stack3956, stack3960, stack3964, stack3968, stack3972, stack3976,
+       stack3980, stack3984, stack3988, stack3992, stack3996, stack4000,
+       stack4004, stack4008, stack4012, stack4016, stack4020, stack4024,
+       stack4028, stack4032, stack4036, stack4040, stack4044, stack4048,
+       stack4052, stack4056, stack4060, stack4064, stack4068, stack4072,
+       stack4076, stack4080, stack4084, stack4088, stack4092, stack4096,
+       stack4100, stack4104, stack4108, stack4112, stack4116, stack4120,
+       stack4124, stack4128, stack4132, stack4136, stack4140, stack4144,
+       stack4148, stack4152, stack4156, stack4160, stack4164, stack4168,
+       stack4172, stack4176, stack4180, stack4184, stack4188, stack4192,
+       stack4196, stack4200, stack4204, stack4208, stack4212, stack4216,
+       stack4220, stack4224, stack4228, stack4232, stack4236, stack4240,
+       stack4244, stack4248, stack4252, stack4256, stack4260, stack4264,
+       stack4268, stack4272, stack4276, stack4280, stack4284, stack4288,
+       stack4292, stack4296, stack4300, stack4304, stack4308, stack4312,
+       stack4316, stack4320, stack4324, stack4328, stack4332, stack4336,
+       stack4340, stack4344, stack4348, stack4352, stack4356, stack4360,
+       stack4364, stack4368, stack4372, stack4376, stack4380, stack4384,
+       stack4388, stack4392, stack4396, stack4400, stack4404, stack4408,
+       stack4412, stack4416, stack4420, stack4424, stack4428, stack4432,
+       stack4436, stack4440, stack4444, stack4448, stack4452, stack4456,
+       stack4460, stack4464, stack4468, stack4472, stack4476, stack4480,
+       stack4484, stack4488, stack4492, stack4496, stack4500, stack4504,
+       stack4508, stack4512, stack4516, stack4520, stack4524, stack4528,
+       stack4532, stack4536, stack4540, stack4544, stack4548, stack4552,
+       stack4556, stack4560, stack4564, stack4568, stack4572, stack4576,
+       stack4580, stack4584, stack4588, stack4592, stack4596, stack4600,
+       stack4604, stack4608, stack4612, stack4616, stack4620, stack4624,
+       stack4628, stack4632, stack4636, stack4640, stack4644, stack4648,
+       stack4652, stack4656, stack4660, stack4664, stack4668, stack4672,
+       stack4676, stack4680, stack4684, stack4688, stack4692, stack4696,
+       stack4700, stack4704, stack4708, stack4712, stack4716, stack4720,
+       stack4724, stack4728, stack4732, stack4736, stack4740, stack4744,
+       stack4748, stack4752, stack4756, stack4760, stack4764, stack4768,
+       stack4772, stack4776, stack4780, stack4784, stack4788, stack4792,
+       stack4796, stack4800, stack4804, stack4808, stack4812, stack4816,
+       stack4820, stack4824, stack4828, stack4832, stack4836, stack4840,
+       stack4844, stack4848, stack4852, stack4856, stack4860, stack4864,
+       stack4868, stack4872, stack4876, stack4880, stack4884, stack4888,
+       stack4892, stack4896, stack4900, stack4904, stack4908, stack4912,
+       stack4916, stack4920, stack4924, stack4928, stack4932, stack4936,
+       stack4940, stack4944, stack4948, stack4952, stack4956, stack4960,
+       stack4964, stack4968, stack4972, stack4976, stack4980, stack4984,
+       stack4988, stack4992, stack4996, stack5000,
+}
+
+// Edit .+1,$ | seq 4 4 5000 | sed 's/.*/func stack&() { var buf [&]byte; use(buf[:]); C.callGoStackCheck() }/'
+func stack4()    { var buf [4]byte; use(buf[:]); C.callGoStackCheck() }
+func stack8()    { var buf [8]byte; use(buf[:]); C.callGoStackCheck() }
+func stack12()   { var buf [12]byte; use(buf[:]); C.callGoStackCheck() }
+func stack16()   { var buf [16]byte; use(buf[:]); C.callGoStackCheck() }
+func stack20()   { var buf [20]byte; use(buf[:]); C.callGoStackCheck() }
+func stack24()   { var buf [24]byte; use(buf[:]); C.callGoStackCheck() }
+func stack28()   { var buf [28]byte; use(buf[:]); C.callGoStackCheck() }
+func stack32()   { var buf [32]byte; use(buf[:]); C.callGoStackCheck() }
+func stack36()   { var buf [36]byte; use(buf[:]); C.callGoStackCheck() }
+func stack40()   { var buf [40]byte; use(buf[:]); C.callGoStackCheck() }
+func stack44()   { var buf [44]byte; use(buf[:]); C.callGoStackCheck() }
+func stack48()   { var buf [48]byte; use(buf[:]); C.callGoStackCheck() }
+func stack52()   { var buf [52]byte; use(buf[:]); C.callGoStackCheck() }
+func stack56()   { var buf [56]byte; use(buf[:]); C.callGoStackCheck() }
+func stack60()   { var buf [60]byte; use(buf[:]); C.callGoStackCheck() }
+func stack64()   { var buf [64]byte; use(buf[:]); C.callGoStackCheck() }
+func stack68()   { var buf [68]byte; use(buf[:]); C.callGoStackCheck() }
+func stack72()   { var buf [72]byte; use(buf[:]); C.callGoStackCheck() }
+func stack76()   { var buf [76]byte; use(buf[:]); C.callGoStackCheck() }
+func stack80()   { var buf [80]byte; use(buf[:]); C.callGoStackCheck() }
+func stack84()   { var buf [84]byte; use(buf[:]); C.callGoStackCheck() }
+func stack88()   { var buf [88]byte; use(buf[:]); C.callGoStackCheck() }
+func stack92()   { var buf [92]byte; use(buf[:]); C.callGoStackCheck() }
+func stack96()   { var buf [96]byte; use(buf[:]); C.callGoStackCheck() }
+func stack100()  { var buf [100]byte; use(buf[:]); C.callGoStackCheck() }
+func stack104()  { var buf [104]byte; use(buf[:]); C.callGoStackCheck() }
+func stack108()  { var buf [108]byte; use(buf[:]); C.callGoStackCheck() }
+func stack112()  { var buf [112]byte; use(buf[:]); C.callGoStackCheck() }
+func stack116()  { var buf [116]byte; use(buf[:]); C.callGoStackCheck() }
+func stack120()  { var buf [120]byte; use(buf[:]); C.callGoStackCheck() }
+func stack124()  { var buf [124]byte; use(buf[:]); C.callGoStackCheck() }
+func stack128()  { var buf [128]byte; use(buf[:]); C.callGoStackCheck() }
+func stack132()  { var buf [132]byte; use(buf[:]); C.callGoStackCheck() }
+func stack136()  { var buf [136]byte; use(buf[:]); C.callGoStackCheck() }
+func stack140()  { var buf [140]byte; use(buf[:]); C.callGoStackCheck() }
+func stack144()  { var buf [144]byte; use(buf[:]); C.callGoStackCheck() }
+func stack148()  { var buf [148]byte; use(buf[:]); C.callGoStackCheck() }
+func stack152()  { var buf [152]byte; use(buf[:]); C.callGoStackCheck() }
+func stack156()  { var buf [156]byte; use(buf[:]); C.callGoStackCheck() }
+func stack160()  { var buf [160]byte; use(buf[:]); C.callGoStackCheck() }
+func stack164()  { var buf [164]byte; use(buf[:]); C.callGoStackCheck() }
+func stack168()  { var buf [168]byte; use(buf[:]); C.callGoStackCheck() }
+func stack172()  { var buf [172]byte; use(buf[:]); C.callGoStackCheck() }
+func stack176()  { var buf [176]byte; use(buf[:]); C.callGoStackCheck() }
+func stack180()  { var buf [180]byte; use(buf[:]); C.callGoStackCheck() }
+func stack184()  { var buf [184]byte; use(buf[:]); C.callGoStackCheck() }
+func stack188()  { var buf [188]byte; use(buf[:]); C.callGoStackCheck() }
+func stack192()  { var buf [192]byte; use(buf[:]); C.callGoStackCheck() }
+func stack196()  { var buf [196]byte; use(buf[:]); C.callGoStackCheck() }
+func stack200()  { var buf [200]byte; use(buf[:]); C.callGoStackCheck() }
+func stack204()  { var buf [204]byte; use(buf[:]); C.callGoStackCheck() }
+func stack208()  { var buf [208]byte; use(buf[:]); C.callGoStackCheck() }
+func stack212()  { var buf [212]byte; use(buf[:]); C.callGoStackCheck() }
+func stack216()  { var buf [216]byte; use(buf[:]); C.callGoStackCheck() }
+func stack220()  { var buf [220]byte; use(buf[:]); C.callGoStackCheck() }
+func stack224()  { var buf [224]byte; use(buf[:]); C.callGoStackCheck() }
+func stack228()  { var buf [228]byte; use(buf[:]); C.callGoStackCheck() }
+func stack232()  { var buf [232]byte; use(buf[:]); C.callGoStackCheck() }
+func stack236()  { var buf [236]byte; use(buf[:]); C.callGoStackCheck() }
+func stack240()  { var buf [240]byte; use(buf[:]); C.callGoStackCheck() }
+func stack244()  { var buf [244]byte; use(buf[:]); C.callGoStackCheck() }
+func stack248()  { var buf [248]byte; use(buf[:]); C.callGoStackCheck() }
+func stack252()  { var buf [252]byte; use(buf[:]); C.callGoStackCheck() }
+func stack256()  { var buf [256]byte; use(buf[:]); C.callGoStackCheck() }
+func stack260()  { var buf [260]byte; use(buf[:]); C.callGoStackCheck() }
+func stack264()  { var buf [264]byte; use(buf[:]); C.callGoStackCheck() }
+func stack268()  { var buf [268]byte; use(buf[:]); C.callGoStackCheck() }
+func stack272()  { var buf [272]byte; use(buf[:]); C.callGoStackCheck() }
+func stack276()  { var buf [276]byte; use(buf[:]); C.callGoStackCheck() }
+func stack280()  { var buf [280]byte; use(buf[:]); C.callGoStackCheck() }
+func stack284()  { var buf [284]byte; use(buf[:]); C.callGoStackCheck() }
+func stack288()  { var buf [288]byte; use(buf[:]); C.callGoStackCheck() }
+func stack292()  { var buf [292]byte; use(buf[:]); C.callGoStackCheck() }
+func stack296()  { var buf [296]byte; use(buf[:]); C.callGoStackCheck() }
+func stack300()  { var buf [300]byte; use(buf[:]); C.callGoStackCheck() }
+func stack304()  { var buf [304]byte; use(buf[:]); C.callGoStackCheck() }
+func stack308()  { var buf [308]byte; use(buf[:]); C.callGoStackCheck() }
+func stack312()  { var buf [312]byte; use(buf[:]); C.callGoStackCheck() }
+func stack316()  { var buf [316]byte; use(buf[:]); C.callGoStackCheck() }
+func stack320()  { var buf [320]byte; use(buf[:]); C.callGoStackCheck() }
+func stack324()  { var buf [324]byte; use(buf[:]); C.callGoStackCheck() }
+func stack328()  { var buf [328]byte; use(buf[:]); C.callGoStackCheck() }
+func stack332()  { var buf [332]byte; use(buf[:]); C.callGoStackCheck() }
+func stack336()  { var buf [336]byte; use(buf[:]); C.callGoStackCheck() }
+func stack340()  { var buf [340]byte; use(buf[:]); C.callGoStackCheck() }
+func stack344()  { var buf [344]byte; use(buf[:]); C.callGoStackCheck() }
+func stack348()  { var buf [348]byte; use(buf[:]); C.callGoStackCheck() }
+func stack352()  { var buf [352]byte; use(buf[:]); C.callGoStackCheck() }
+func stack356()  { var buf [356]byte; use(buf[:]); C.callGoStackCheck() }
+func stack360()  { var buf [360]byte; use(buf[:]); C.callGoStackCheck() }
+func stack364()  { var buf [364]byte; use(buf[:]); C.callGoStackCheck() }
+func stack368()  { var buf [368]byte; use(buf[:]); C.callGoStackCheck() }
+func stack372()  { var buf [372]byte; use(buf[:]); C.callGoStackCheck() }
+func stack376()  { var buf [376]byte; use(buf[:]); C.callGoStackCheck() }
+func stack380()  { var buf [380]byte; use(buf[:]); C.callGoStackCheck() }
+func stack384()  { var buf [384]byte; use(buf[:]); C.callGoStackCheck() }
+func stack388()  { var buf [388]byte; use(buf[:]); C.callGoStackCheck() }
+func stack392()  { var buf [392]byte; use(buf[:]); C.callGoStackCheck() }
+func stack396()  { var buf [396]byte; use(buf[:]); C.callGoStackCheck() }
+func stack400()  { var buf [400]byte; use(buf[:]); C.callGoStackCheck() }
+func stack404()  { var buf [404]byte; use(buf[:]); C.callGoStackCheck() }
+func stack408()  { var buf [408]byte; use(buf[:]); C.callGoStackCheck() }
+func stack412()  { var buf [412]byte; use(buf[:]); C.callGoStackCheck() }
+func stack416()  { var buf [416]byte; use(buf[:]); C.callGoStackCheck() }
+func stack420()  { var buf [420]byte; use(buf[:]); C.callGoStackCheck() }
+func stack424()  { var buf [424]byte; use(buf[:]); C.callGoStackCheck() }
+func stack428()  { var buf [428]byte; use(buf[:]); C.callGoStackCheck() }
+func stack432()  { var buf [432]byte; use(buf[:]); C.callGoStackCheck() }
+func stack436()  { var buf [436]byte; use(buf[:]); C.callGoStackCheck() }
+func stack440()  { var buf [440]byte; use(buf[:]); C.callGoStackCheck() }
+func stack444()  { var buf [444]byte; use(buf[:]); C.callGoStackCheck() }
+func stack448()  { var buf [448]byte; use(buf[:]); C.callGoStackCheck() }
+func stack452()  { var buf [452]byte; use(buf[:]); C.callGoStackCheck() }
+func stack456()  { var buf [456]byte; use(buf[:]); C.callGoStackCheck() }
+func stack460()  { var buf [460]byte; use(buf[:]); C.callGoStackCheck() }
+func stack464()  { var buf [464]byte; use(buf[:]); C.callGoStackCheck() }
+func stack468()  { var buf [468]byte; use(buf[:]); C.callGoStackCheck() }
+func stack472()  { var buf [472]byte; use(buf[:]); C.callGoStackCheck() }
+func stack476()  { var buf [476]byte; use(buf[:]); C.callGoStackCheck() }
+func stack480()  { var buf [480]byte; use(buf[:]); C.callGoStackCheck() }
+func stack484()  { var buf [484]byte; use(buf[:]); C.callGoStackCheck() }
+func stack488()  { var buf [488]byte; use(buf[:]); C.callGoStackCheck() }
+func stack492()  { var buf [492]byte; use(buf[:]); C.callGoStackCheck() }
+func stack496()  { var buf [496]byte; use(buf[:]); C.callGoStackCheck() }
+func stack500()  { var buf [500]byte; use(buf[:]); C.callGoStackCheck() }
+func stack504()  { var buf [504]byte; use(buf[:]); C.callGoStackCheck() }
+func stack508()  { var buf [508]byte; use(buf[:]); C.callGoStackCheck() }
+func stack512()  { var buf [512]byte; use(buf[:]); C.callGoStackCheck() }
+func stack516()  { var buf [516]byte; use(buf[:]); C.callGoStackCheck() }
+func stack520()  { var buf [520]byte; use(buf[:]); C.callGoStackCheck() }
+func stack524()  { var buf [524]byte; use(buf[:]); C.callGoStackCheck() }
+func stack528()  { var buf [528]byte; use(buf[:]); C.callGoStackCheck() }
+func stack532()  { var buf [532]byte; use(buf[:]); C.callGoStackCheck() }
+func stack536()  { var buf [536]byte; use(buf[:]); C.callGoStackCheck() }
+func stack540()  { var buf [540]byte; use(buf[:]); C.callGoStackCheck() }
+func stack544()  { var buf [544]byte; use(buf[:]); C.callGoStackCheck() }
+func stack548()  { var buf [548]byte; use(buf[:]); C.callGoStackCheck() }
+func stack552()  { var buf [552]byte; use(buf[:]); C.callGoStackCheck() }
+func stack556()  { var buf [556]byte; use(buf[:]); C.callGoStackCheck() }
+func stack560()  { var buf [560]byte; use(buf[:]); C.callGoStackCheck() }
+func stack564()  { var buf [564]byte; use(buf[:]); C.callGoStackCheck() }
+func stack568()  { var buf [568]byte; use(buf[:]); C.callGoStackCheck() }
+func stack572()  { var buf [572]byte; use(buf[:]); C.callGoStackCheck() }
+func stack576()  { var buf [576]byte; use(buf[:]); C.callGoStackCheck() }
+func stack580()  { var buf [580]byte; use(buf[:]); C.callGoStackCheck() }
+func stack584()  { var buf [584]byte; use(buf[:]); C.callGoStackCheck() }
+func stack588()  { var buf [588]byte; use(buf[:]); C.callGoStackCheck() }
+func stack592()  { var buf [592]byte; use(buf[:]); C.callGoStackCheck() }
+func stack596()  { var buf [596]byte; use(buf[:]); C.callGoStackCheck() }
+func stack600()  { var buf [600]byte; use(buf[:]); C.callGoStackCheck() }
+func stack604()  { var buf [604]byte; use(buf[:]); C.callGoStackCheck() }
+func stack608()  { var buf [608]byte; use(buf[:]); C.callGoStackCheck() }
+func stack612()  { var buf [612]byte; use(buf[:]); C.callGoStackCheck() }
+func stack616()  { var buf [616]byte; use(buf[:]); C.callGoStackCheck() }
+func stack620()  { var buf [620]byte; use(buf[:]); C.callGoStackCheck() }
+func stack624()  { var buf [624]byte; use(buf[:]); C.callGoStackCheck() }
+func stack628()  { var buf [628]byte; use(buf[:]); C.callGoStackCheck() }
+func stack632()  { var buf [632]byte; use(buf[:]); C.callGoStackCheck() }
+func stack636()  { var buf [636]byte; use(buf[:]); C.callGoStackCheck() }
+func stack640()  { var buf [640]byte; use(buf[:]); C.callGoStackCheck() }
+func stack644()  { var buf [644]byte; use(buf[:]); C.callGoStackCheck() }
+func stack648()  { var buf [648]byte; use(buf[:]); C.callGoStackCheck() }
+func stack652()  { var buf [652]byte; use(buf[:]); C.callGoStackCheck() }
+func stack656()  { var buf [656]byte; use(buf[:]); C.callGoStackCheck() }
+func stack660()  { var buf [660]byte; use(buf[:]); C.callGoStackCheck() }
+func stack664()  { var buf [664]byte; use(buf[:]); C.callGoStackCheck() }
+func stack668()  { var buf [668]byte; use(buf[:]); C.callGoStackCheck() }
+func stack672()  { var buf [672]byte; use(buf[:]); C.callGoStackCheck() }
+func stack676()  { var buf [676]byte; use(buf[:]); C.callGoStackCheck() }
+func stack680()  { var buf [680]byte; use(buf[:]); C.callGoStackCheck() }
+func stack684()  { var buf [684]byte; use(buf[:]); C.callGoStackCheck() }
+func stack688()  { var buf [688]byte; use(buf[:]); C.callGoStackCheck() }
+func stack692()  { var buf [692]byte; use(buf[:]); C.callGoStackCheck() }
+func stack696()  { var buf [696]byte; use(buf[:]); C.callGoStackCheck() }
+func stack700()  { var buf [700]byte; use(buf[:]); C.callGoStackCheck() }
+func stack704()  { var buf [704]byte; use(buf[:]); C.callGoStackCheck() }
+func stack708()  { var buf [708]byte; use(buf[:]); C.callGoStackCheck() }
+func stack712()  { var buf [712]byte; use(buf[:]); C.callGoStackCheck() }
+func stack716()  { var buf [716]byte; use(buf[:]); C.callGoStackCheck() }
+func stack720()  { var buf [720]byte; use(buf[:]); C.callGoStackCheck() }
+func stack724()  { var buf [724]byte; use(buf[:]); C.callGoStackCheck() }
+func stack728()  { var buf [728]byte; use(buf[:]); C.callGoStackCheck() }
+func stack732()  { var buf [732]byte; use(buf[:]); C.callGoStackCheck() }
+func stack736()  { var buf [736]byte; use(buf[:]); C.callGoStackCheck() }
+func stack740()  { var buf [740]byte; use(buf[:]); C.callGoStackCheck() }
+func stack744()  { var buf [744]byte; use(buf[:]); C.callGoStackCheck() }
+func stack748()  { var buf [748]byte; use(buf[:]); C.callGoStackCheck() }
+func stack752()  { var buf [752]byte; use(buf[:]); C.callGoStackCheck() }
+func stack756()  { var buf [756]byte; use(buf[:]); C.callGoStackCheck() }
+func stack760()  { var buf [760]byte; use(buf[:]); C.callGoStackCheck() }
+func stack764()  { var buf [764]byte; use(buf[:]); C.callGoStackCheck() }
+func stack768()  { var buf [768]byte; use(buf[:]); C.callGoStackCheck() }
+func stack772()  { var buf [772]byte; use(buf[:]); C.callGoStackCheck() }
+func stack776()  { var buf [776]byte; use(buf[:]); C.callGoStackCheck() }
+func stack780()  { var buf [780]byte; use(buf[:]); C.callGoStackCheck() }
+func stack784()  { var buf [784]byte; use(buf[:]); C.callGoStackCheck() }
+func stack788()  { var buf [788]byte; use(buf[:]); C.callGoStackCheck() }
+func stack792()  { var buf [792]byte; use(buf[:]); C.callGoStackCheck() }
+func stack796()  { var buf [796]byte; use(buf[:]); C.callGoStackCheck() }
+func stack800()  { var buf [800]byte; use(buf[:]); C.callGoStackCheck() }
+func stack804()  { var buf [804]byte; use(buf[:]); C.callGoStackCheck() }
+func stack808()  { var buf [808]byte; use(buf[:]); C.callGoStackCheck() }
+func stack812()  { var buf [812]byte; use(buf[:]); C.callGoStackCheck() }
+func stack816()  { var buf [816]byte; use(buf[:]); C.callGoStackCheck() }
+func stack820()  { var buf [820]byte; use(buf[:]); C.callGoStackCheck() }
+func stack824()  { var buf [824]byte; use(buf[:]); C.callGoStackCheck() }
+func stack828()  { var buf [828]byte; use(buf[:]); C.callGoStackCheck() }
+func stack832()  { var buf [832]byte; use(buf[:]); C.callGoStackCheck() }
+func stack836()  { var buf [836]byte; use(buf[:]); C.callGoStackCheck() }
+func stack840()  { var buf [840]byte; use(buf[:]); C.callGoStackCheck() }
+func stack844()  { var buf [844]byte; use(buf[:]); C.callGoStackCheck() }
+func stack848()  { var buf [848]byte; use(buf[:]); C.callGoStackCheck() }
+func stack852()  { var buf [852]byte; use(buf[:]); C.callGoStackCheck() }
+func stack856()  { var buf [856]byte; use(buf[:]); C.callGoStackCheck() }
+func stack860()  { var buf [860]byte; use(buf[:]); C.callGoStackCheck() }
+func stack864()  { var buf [864]byte; use(buf[:]); C.callGoStackCheck() }
+func stack868()  { var buf [868]byte; use(buf[:]); C.callGoStackCheck() }
+func stack872()  { var buf [872]byte; use(buf[:]); C.callGoStackCheck() }
+func stack876()  { var buf [876]byte; use(buf[:]); C.callGoStackCheck() }
+func stack880()  { var buf [880]byte; use(buf[:]); C.callGoStackCheck() }
+func stack884()  { var buf [884]byte; use(buf[:]); C.callGoStackCheck() }
+func stack888()  { var buf [888]byte; use(buf[:]); C.callGoStackCheck() }
+func stack892()  { var buf [892]byte; use(buf[:]); C.callGoStackCheck() }
+func stack896()  { var buf [896]byte; use(buf[:]); C.callGoStackCheck() }
+func stack900()  { var buf [900]byte; use(buf[:]); C.callGoStackCheck() }
+func stack904()  { var buf [904]byte; use(buf[:]); C.callGoStackCheck() }
+func stack908()  { var buf [908]byte; use(buf[:]); C.callGoStackCheck() }
+func stack912()  { var buf [912]byte; use(buf[:]); C.callGoStackCheck() }
+func stack916()  { var buf [916]byte; use(buf[:]); C.callGoStackCheck() }
+func stack920()  { var buf [920]byte; use(buf[:]); C.callGoStackCheck() }
+func stack924()  { var buf [924]byte; use(buf[:]); C.callGoStackCheck() }
+func stack928()  { var buf [928]byte; use(buf[:]); C.callGoStackCheck() }
+func stack932()  { var buf [932]byte; use(buf[:]); C.callGoStackCheck() }
+func stack936()  { var buf [936]byte; use(buf[:]); C.callGoStackCheck() }
+func stack940()  { var buf [940]byte; use(buf[:]); C.callGoStackCheck() }
+func stack944()  { var buf [944]byte; use(buf[:]); C.callGoStackCheck() }
+func stack948()  { var buf [948]byte; use(buf[:]); C.callGoStackCheck() }
+func stack952()  { var buf [952]byte; use(buf[:]); C.callGoStackCheck() }
+func stack956()  { var buf [956]byte; use(buf[:]); C.callGoStackCheck() }
+func stack960()  { var buf [960]byte; use(buf[:]); C.callGoStackCheck() }
+func stack964()  { var buf [964]byte; use(buf[:]); C.callGoStackCheck() }
+func stack968()  { var buf [968]byte; use(buf[:]); C.callGoStackCheck() }
+func stack972()  { var buf [972]byte; use(buf[:]); C.callGoStackCheck() }
+func stack976()  { var buf [976]byte; use(buf[:]); C.callGoStackCheck() }
+func stack980()  { var buf [980]byte; use(buf[:]); C.callGoStackCheck() }
+func stack984()  { var buf [984]byte; use(buf[:]); C.callGoStackCheck() }
+func stack988()  { var buf [988]byte; use(buf[:]); C.callGoStackCheck() }
+func stack992()  { var buf [992]byte; use(buf[:]); C.callGoStackCheck() }
+func stack996()  { var buf [996]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1000() { var buf [1000]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1004() { var buf [1004]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1008() { var buf [1008]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1012() { var buf [1012]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1016() { var buf [1016]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1020() { var buf [1020]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1024() { var buf [1024]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1028() { var buf [1028]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1032() { var buf [1032]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1036() { var buf [1036]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1040() { var buf [1040]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1044() { var buf [1044]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1048() { var buf [1048]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1052() { var buf [1052]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1056() { var buf [1056]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1060() { var buf [1060]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1064() { var buf [1064]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1068() { var buf [1068]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1072() { var buf [1072]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1076() { var buf [1076]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1080() { var buf [1080]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1084() { var buf [1084]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1088() { var buf [1088]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1092() { var buf [1092]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1096() { var buf [1096]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1100() { var buf [1100]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1104() { var buf [1104]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1108() { var buf [1108]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1112() { var buf [1112]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1116() { var buf [1116]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1120() { var buf [1120]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1124() { var buf [1124]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1128() { var buf [1128]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1132() { var buf [1132]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1136() { var buf [1136]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1140() { var buf [1140]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1144() { var buf [1144]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1148() { var buf [1148]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1152() { var buf [1152]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1156() { var buf [1156]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1160() { var buf [1160]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1164() { var buf [1164]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1168() { var buf [1168]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1172() { var buf [1172]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1176() { var buf [1176]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1180() { var buf [1180]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1184() { var buf [1184]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1188() { var buf [1188]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1192() { var buf [1192]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1196() { var buf [1196]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1200() { var buf [1200]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1204() { var buf [1204]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1208() { var buf [1208]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1212() { var buf [1212]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1216() { var buf [1216]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1220() { var buf [1220]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1224() { var buf [1224]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1228() { var buf [1228]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1232() { var buf [1232]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1236() { var buf [1236]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1240() { var buf [1240]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1244() { var buf [1244]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1248() { var buf [1248]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1252() { var buf [1252]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1256() { var buf [1256]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1260() { var buf [1260]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1264() { var buf [1264]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1268() { var buf [1268]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1272() { var buf [1272]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1276() { var buf [1276]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1280() { var buf [1280]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1284() { var buf [1284]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1288() { var buf [1288]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1292() { var buf [1292]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1296() { var buf [1296]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1300() { var buf [1300]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1304() { var buf [1304]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1308() { var buf [1308]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1312() { var buf [1312]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1316() { var buf [1316]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1320() { var buf [1320]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1324() { var buf [1324]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1328() { var buf [1328]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1332() { var buf [1332]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1336() { var buf [1336]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1340() { var buf [1340]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1344() { var buf [1344]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1348() { var buf [1348]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1352() { var buf [1352]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1356() { var buf [1356]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1360() { var buf [1360]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1364() { var buf [1364]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1368() { var buf [1368]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1372() { var buf [1372]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1376() { var buf [1376]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1380() { var buf [1380]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1384() { var buf [1384]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1388() { var buf [1388]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1392() { var buf [1392]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1396() { var buf [1396]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1400() { var buf [1400]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1404() { var buf [1404]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1408() { var buf [1408]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1412() { var buf [1412]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1416() { var buf [1416]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1420() { var buf [1420]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1424() { var buf [1424]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1428() { var buf [1428]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1432() { var buf [1432]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1436() { var buf [1436]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1440() { var buf [1440]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1444() { var buf [1444]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1448() { var buf [1448]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1452() { var buf [1452]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1456() { var buf [1456]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1460() { var buf [1460]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1464() { var buf [1464]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1468() { var buf [1468]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1472() { var buf [1472]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1476() { var buf [1476]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1480() { var buf [1480]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1484() { var buf [1484]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1488() { var buf [1488]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1492() { var buf [1492]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1496() { var buf [1496]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1500() { var buf [1500]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1504() { var buf [1504]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1508() { var buf [1508]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1512() { var buf [1512]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1516() { var buf [1516]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1520() { var buf [1520]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1524() { var buf [1524]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1528() { var buf [1528]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1532() { var buf [1532]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1536() { var buf [1536]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1540() { var buf [1540]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1544() { var buf [1544]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1548() { var buf [1548]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1552() { var buf [1552]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1556() { var buf [1556]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1560() { var buf [1560]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1564() { var buf [1564]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1568() { var buf [1568]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1572() { var buf [1572]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1576() { var buf [1576]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1580() { var buf [1580]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1584() { var buf [1584]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1588() { var buf [1588]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1592() { var buf [1592]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1596() { var buf [1596]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1600() { var buf [1600]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1604() { var buf [1604]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1608() { var buf [1608]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1612() { var buf [1612]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1616() { var buf [1616]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1620() { var buf [1620]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1624() { var buf [1624]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1628() { var buf [1628]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1632() { var buf [1632]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1636() { var buf [1636]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1640() { var buf [1640]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1644() { var buf [1644]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1648() { var buf [1648]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1652() { var buf [1652]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1656() { var buf [1656]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1660() { var buf [1660]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1664() { var buf [1664]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1668() { var buf [1668]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1672() { var buf [1672]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1676() { var buf [1676]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1680() { var buf [1680]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1684() { var buf [1684]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1688() { var buf [1688]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1692() { var buf [1692]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1696() { var buf [1696]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1700() { var buf [1700]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1704() { var buf [1704]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1708() { var buf [1708]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1712() { var buf [1712]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1716() { var buf [1716]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1720() { var buf [1720]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1724() { var buf [1724]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1728() { var buf [1728]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1732() { var buf [1732]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1736() { var buf [1736]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1740() { var buf [1740]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1744() { var buf [1744]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1748() { var buf [1748]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1752() { var buf [1752]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1756() { var buf [1756]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1760() { var buf [1760]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1764() { var buf [1764]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1768() { var buf [1768]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1772() { var buf [1772]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1776() { var buf [1776]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1780() { var buf [1780]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1784() { var buf [1784]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1788() { var buf [1788]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1792() { var buf [1792]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1796() { var buf [1796]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1800() { var buf [1800]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1804() { var buf [1804]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1808() { var buf [1808]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1812() { var buf [1812]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1816() { var buf [1816]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1820() { var buf [1820]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1824() { var buf [1824]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1828() { var buf [1828]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1832() { var buf [1832]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1836() { var buf [1836]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1840() { var buf [1840]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1844() { var buf [1844]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1848() { var buf [1848]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1852() { var buf [1852]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1856() { var buf [1856]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1860() { var buf [1860]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1864() { var buf [1864]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1868() { var buf [1868]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1872() { var buf [1872]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1876() { var buf [1876]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1880() { var buf [1880]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1884() { var buf [1884]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1888() { var buf [1888]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1892() { var buf [1892]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1896() { var buf [1896]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1900() { var buf [1900]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1904() { var buf [1904]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1908() { var buf [1908]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1912() { var buf [1912]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1916() { var buf [1916]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1920() { var buf [1920]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1924() { var buf [1924]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1928() { var buf [1928]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1932() { var buf [1932]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1936() { var buf [1936]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1940() { var buf [1940]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1944() { var buf [1944]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1948() { var buf [1948]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1952() { var buf [1952]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1956() { var buf [1956]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1960() { var buf [1960]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1964() { var buf [1964]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1968() { var buf [1968]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1972() { var buf [1972]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1976() { var buf [1976]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1980() { var buf [1980]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1984() { var buf [1984]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1988() { var buf [1988]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1992() { var buf [1992]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1996() { var buf [1996]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2000() { var buf [2000]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2004() { var buf [2004]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2008() { var buf [2008]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2012() { var buf [2012]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2016() { var buf [2016]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2020() { var buf [2020]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2024() { var buf [2024]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2028() { var buf [2028]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2032() { var buf [2032]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2036() { var buf [2036]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2040() { var buf [2040]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2044() { var buf [2044]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2048() { var buf [2048]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2052() { var buf [2052]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2056() { var buf [2056]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2060() { var buf [2060]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2064() { var buf [2064]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2068() { var buf [2068]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2072() { var buf [2072]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2076() { var buf [2076]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2080() { var buf [2080]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2084() { var buf [2084]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2088() { var buf [2088]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2092() { var buf [2092]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2096() { var buf [2096]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2100() { var buf [2100]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2104() { var buf [2104]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2108() { var buf [2108]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2112() { var buf [2112]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2116() { var buf [2116]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2120() { var buf [2120]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2124() { var buf [2124]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2128() { var buf [2128]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2132() { var buf [2132]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2136() { var buf [2136]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2140() { var buf [2140]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2144() { var buf [2144]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2148() { var buf [2148]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2152() { var buf [2152]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2156() { var buf [2156]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2160() { var buf [2160]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2164() { var buf [2164]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2168() { var buf [2168]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2172() { var buf [2172]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2176() { var buf [2176]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2180() { var buf [2180]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2184() { var buf [2184]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2188() { var buf [2188]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2192() { var buf [2192]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2196() { var buf [2196]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2200() { var buf [2200]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2204() { var buf [2204]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2208() { var buf [2208]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2212() { var buf [2212]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2216() { var buf [2216]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2220() { var buf [2220]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2224() { var buf [2224]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2228() { var buf [2228]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2232() { var buf [2232]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2236() { var buf [2236]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2240() { var buf [2240]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2244() { var buf [2244]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2248() { var buf [2248]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2252() { var buf [2252]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2256() { var buf [2256]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2260() { var buf [2260]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2264() { var buf [2264]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2268() { var buf [2268]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2272() { var buf [2272]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2276() { var buf [2276]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2280() { var buf [2280]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2284() { var buf [2284]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2288() { var buf [2288]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2292() { var buf [2292]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2296() { var buf [2296]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2300() { var buf [2300]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2304() { var buf [2304]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2308() { var buf [2308]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2312() { var buf [2312]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2316() { var buf [2316]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2320() { var buf [2320]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2324() { var buf [2324]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2328() { var buf [2328]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2332() { var buf [2332]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2336() { var buf [2336]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2340() { var buf [2340]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2344() { var buf [2344]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2348() { var buf [2348]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2352() { var buf [2352]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2356() { var buf [2356]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2360() { var buf [2360]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2364() { var buf [2364]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2368() { var buf [2368]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2372() { var buf [2372]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2376() { var buf [2376]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2380() { var buf [2380]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2384() { var buf [2384]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2388() { var buf [2388]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2392() { var buf [2392]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2396() { var buf [2396]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2400() { var buf [2400]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2404() { var buf [2404]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2408() { var buf [2408]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2412() { var buf [2412]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2416() { var buf [2416]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2420() { var buf [2420]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2424() { var buf [2424]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2428() { var buf [2428]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2432() { var buf [2432]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2436() { var buf [2436]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2440() { var buf [2440]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2444() { var buf [2444]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2448() { var buf [2448]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2452() { var buf [2452]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2456() { var buf [2456]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2460() { var buf [2460]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2464() { var buf [2464]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2468() { var buf [2468]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2472() { var buf [2472]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2476() { var buf [2476]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2480() { var buf [2480]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2484() { var buf [2484]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2488() { var buf [2488]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2492() { var buf [2492]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2496() { var buf [2496]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2500() { var buf [2500]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2504() { var buf [2504]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2508() { var buf [2508]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2512() { var buf [2512]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2516() { var buf [2516]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2520() { var buf [2520]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2524() { var buf [2524]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2528() { var buf [2528]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2532() { var buf [2532]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2536() { var buf [2536]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2540() { var buf [2540]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2544() { var buf [2544]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2548() { var buf [2548]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2552() { var buf [2552]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2556() { var buf [2556]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2560() { var buf [2560]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2564() { var buf [2564]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2568() { var buf [2568]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2572() { var buf [2572]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2576() { var buf [2576]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2580() { var buf [2580]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2584() { var buf [2584]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2588() { var buf [2588]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2592() { var buf [2592]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2596() { var buf [2596]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2600() { var buf [2600]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2604() { var buf [2604]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2608() { var buf [2608]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2612() { var buf [2612]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2616() { var buf [2616]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2620() { var buf [2620]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2624() { var buf [2624]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2628() { var buf [2628]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2632() { var buf [2632]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2636() { var buf [2636]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2640() { var buf [2640]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2644() { var buf [2644]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2648() { var buf [2648]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2652() { var buf [2652]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2656() { var buf [2656]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2660() { var buf [2660]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2664() { var buf [2664]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2668() { var buf [2668]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2672() { var buf [2672]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2676() { var buf [2676]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2680() { var buf [2680]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2684() { var buf [2684]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2688() { var buf [2688]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2692() { var buf [2692]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2696() { var buf [2696]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2700() { var buf [2700]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2704() { var buf [2704]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2708() { var buf [2708]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2712() { var buf [2712]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2716() { var buf [2716]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2720() { var buf [2720]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2724() { var buf [2724]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2728() { var buf [2728]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2732() { var buf [2732]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2736() { var buf [2736]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2740() { var buf [2740]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2744() { var buf [2744]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2748() { var buf [2748]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2752() { var buf [2752]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2756() { var buf [2756]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2760() { var buf [2760]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2764() { var buf [2764]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2768() { var buf [2768]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2772() { var buf [2772]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2776() { var buf [2776]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2780() { var buf [2780]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2784() { var buf [2784]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2788() { var buf [2788]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2792() { var buf [2792]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2796() { var buf [2796]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2800() { var buf [2800]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2804() { var buf [2804]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2808() { var buf [2808]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2812() { var buf [2812]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2816() { var buf [2816]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2820() { var buf [2820]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2824() { var buf [2824]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2828() { var buf [2828]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2832() { var buf [2832]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2836() { var buf [2836]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2840() { var buf [2840]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2844() { var buf [2844]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2848() { var buf [2848]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2852() { var buf [2852]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2856() { var buf [2856]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2860() { var buf [2860]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2864() { var buf [2864]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2868() { var buf [2868]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2872() { var buf [2872]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2876() { var buf [2876]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2880() { var buf [2880]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2884() { var buf [2884]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2888() { var buf [2888]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2892() { var buf [2892]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2896() { var buf [2896]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2900() { var buf [2900]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2904() { var buf [2904]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2908() { var buf [2908]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2912() { var buf [2912]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2916() { var buf [2916]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2920() { var buf [2920]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2924() { var buf [2924]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2928() { var buf [2928]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2932() { var buf [2932]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2936() { var buf [2936]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2940() { var buf [2940]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2944() { var buf [2944]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2948() { var buf [2948]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2952() { var buf [2952]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2956() { var buf [2956]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2960() { var buf [2960]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2964() { var buf [2964]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2968() { var buf [2968]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2972() { var buf [2972]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2976() { var buf [2976]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2980() { var buf [2980]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2984() { var buf [2984]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2988() { var buf [2988]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2992() { var buf [2992]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2996() { var buf [2996]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3000() { var buf [3000]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3004() { var buf [3004]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3008() { var buf [3008]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3012() { var buf [3012]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3016() { var buf [3016]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3020() { var buf [3020]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3024() { var buf [3024]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3028() { var buf [3028]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3032() { var buf [3032]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3036() { var buf [3036]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3040() { var buf [3040]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3044() { var buf [3044]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3048() { var buf [3048]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3052() { var buf [3052]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3056() { var buf [3056]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3060() { var buf [3060]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3064() { var buf [3064]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3068() { var buf [3068]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3072() { var buf [3072]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3076() { var buf [3076]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3080() { var buf [3080]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3084() { var buf [3084]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3088() { var buf [3088]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3092() { var buf [3092]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3096() { var buf [3096]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3100() { var buf [3100]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3104() { var buf [3104]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3108() { var buf [3108]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3112() { var buf [3112]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3116() { var buf [3116]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3120() { var buf [3120]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3124() { var buf [3124]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3128() { var buf [3128]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3132() { var buf [3132]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3136() { var buf [3136]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3140() { var buf [3140]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3144() { var buf [3144]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3148() { var buf [3148]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3152() { var buf [3152]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3156() { var buf [3156]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3160() { var buf [3160]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3164() { var buf [3164]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3168() { var buf [3168]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3172() { var buf [3172]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3176() { var buf [3176]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3180() { var buf [3180]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3184() { var buf [3184]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3188() { var buf [3188]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3192() { var buf [3192]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3196() { var buf [3196]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3200() { var buf [3200]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3204() { var buf [3204]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3208() { var buf [3208]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3212() { var buf [3212]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3216() { var buf [3216]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3220() { var buf [3220]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3224() { var buf [3224]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3228() { var buf [3228]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3232() { var buf [3232]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3236() { var buf [3236]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3240() { var buf [3240]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3244() { var buf [3244]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3248() { var buf [3248]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3252() { var buf [3252]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3256() { var buf [3256]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3260() { var buf [3260]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3264() { var buf [3264]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3268() { var buf [3268]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3272() { var buf [3272]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3276() { var buf [3276]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3280() { var buf [3280]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3284() { var buf [3284]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3288() { var buf [3288]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3292() { var buf [3292]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3296() { var buf [3296]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3300() { var buf [3300]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3304() { var buf [3304]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3308() { var buf [3308]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3312() { var buf [3312]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3316() { var buf [3316]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3320() { var buf [3320]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3324() { var buf [3324]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3328() { var buf [3328]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3332() { var buf [3332]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3336() { var buf [3336]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3340() { var buf [3340]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3344() { var buf [3344]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3348() { var buf [3348]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3352() { var buf [3352]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3356() { var buf [3356]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3360() { var buf [3360]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3364() { var buf [3364]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3368() { var buf [3368]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3372() { var buf [3372]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3376() { var buf [3376]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3380() { var buf [3380]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3384() { var buf [3384]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3388() { var buf [3388]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3392() { var buf [3392]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3396() { var buf [3396]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3400() { var buf [3400]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3404() { var buf [3404]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3408() { var buf [3408]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3412() { var buf [3412]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3416() { var buf [3416]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3420() { var buf [3420]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3424() { var buf [3424]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3428() { var buf [3428]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3432() { var buf [3432]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3436() { var buf [3436]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3440() { var buf [3440]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3444() { var buf [3444]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3448() { var buf [3448]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3452() { var buf [3452]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3456() { var buf [3456]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3460() { var buf [3460]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3464() { var buf [3464]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3468() { var buf [3468]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3472() { var buf [3472]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3476() { var buf [3476]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3480() { var buf [3480]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3484() { var buf [3484]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3488() { var buf [3488]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3492() { var buf [3492]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3496() { var buf [3496]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3500() { var buf [3500]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3504() { var buf [3504]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3508() { var buf [3508]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3512() { var buf [3512]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3516() { var buf [3516]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3520() { var buf [3520]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3524() { var buf [3524]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3528() { var buf [3528]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3532() { var buf [3532]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3536() { var buf [3536]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3540() { var buf [3540]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3544() { var buf [3544]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3548() { var buf [3548]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3552() { var buf [3552]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3556() { var buf [3556]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3560() { var buf [3560]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3564() { var buf [3564]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3568() { var buf [3568]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3572() { var buf [3572]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3576() { var buf [3576]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3580() { var buf [3580]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3584() { var buf [3584]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3588() { var buf [3588]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3592() { var buf [3592]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3596() { var buf [3596]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3600() { var buf [3600]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3604() { var buf [3604]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3608() { var buf [3608]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3612() { var buf [3612]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3616() { var buf [3616]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3620() { var buf [3620]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3624() { var buf [3624]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3628() { var buf [3628]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3632() { var buf [3632]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3636() { var buf [3636]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3640() { var buf [3640]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3644() { var buf [3644]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3648() { var buf [3648]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3652() { var buf [3652]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3656() { var buf [3656]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3660() { var buf [3660]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3664() { var buf [3664]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3668() { var buf [3668]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3672() { var buf [3672]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3676() { var buf [3676]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3680() { var buf [3680]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3684() { var buf [3684]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3688() { var buf [3688]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3692() { var buf [3692]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3696() { var buf [3696]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3700() { var buf [3700]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3704() { var buf [3704]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3708() { var buf [3708]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3712() { var buf [3712]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3716() { var buf [3716]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3720() { var buf [3720]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3724() { var buf [3724]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3728() { var buf [3728]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3732() { var buf [3732]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3736() { var buf [3736]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3740() { var buf [3740]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3744() { var buf [3744]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3748() { var buf [3748]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3752() { var buf [3752]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3756() { var buf [3756]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3760() { var buf [3760]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3764() { var buf [3764]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3768() { var buf [3768]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3772() { var buf [3772]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3776() { var buf [3776]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3780() { var buf [3780]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3784() { var buf [3784]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3788() { var buf [3788]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3792() { var buf [3792]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3796() { var buf [3796]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3800() { var buf [3800]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3804() { var buf [3804]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3808() { var buf [3808]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3812() { var buf [3812]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3816() { var buf [3816]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3820() { var buf [3820]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3824() { var buf [3824]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3828() { var buf [3828]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3832() { var buf [3832]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3836() { var buf [3836]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3840() { var buf [3840]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3844() { var buf [3844]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3848() { var buf [3848]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3852() { var buf [3852]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3856() { var buf [3856]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3860() { var buf [3860]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3864() { var buf [3864]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3868() { var buf [3868]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3872() { var buf [3872]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3876() { var buf [3876]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3880() { var buf [3880]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3884() { var buf [3884]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3888() { var buf [3888]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3892() { var buf [3892]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3896() { var buf [3896]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3900() { var buf [3900]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3904() { var buf [3904]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3908() { var buf [3908]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3912() { var buf [3912]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3916() { var buf [3916]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3920() { var buf [3920]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3924() { var buf [3924]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3928() { var buf [3928]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3932() { var buf [3932]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3936() { var buf [3936]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3940() { var buf [3940]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3944() { var buf [3944]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3948() { var buf [3948]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3952() { var buf [3952]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3956() { var buf [3956]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3960() { var buf [3960]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3964() { var buf [3964]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3968() { var buf [3968]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3972() { var buf [3972]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3976() { var buf [3976]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3980() { var buf [3980]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3984() { var buf [3984]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3988() { var buf [3988]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3992() { var buf [3992]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3996() { var buf [3996]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4000() { var buf [4000]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4004() { var buf [4004]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4008() { var buf [4008]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4012() { var buf [4012]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4016() { var buf [4016]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4020() { var buf [4020]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4024() { var buf [4024]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4028() { var buf [4028]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4032() { var buf [4032]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4036() { var buf [4036]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4040() { var buf [4040]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4044() { var buf [4044]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4048() { var buf [4048]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4052() { var buf [4052]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4056() { var buf [4056]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4060() { var buf [4060]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4064() { var buf [4064]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4068() { var buf [4068]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4072() { var buf [4072]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4076() { var buf [4076]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4080() { var buf [4080]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4084() { var buf [4084]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4088() { var buf [4088]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4092() { var buf [4092]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4096() { var buf [4096]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4100() { var buf [4100]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4104() { var buf [4104]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4108() { var buf [4108]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4112() { var buf [4112]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4116() { var buf [4116]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4120() { var buf [4120]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4124() { var buf [4124]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4128() { var buf [4128]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4132() { var buf [4132]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4136() { var buf [4136]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4140() { var buf [4140]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4144() { var buf [4144]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4148() { var buf [4148]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4152() { var buf [4152]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4156() { var buf [4156]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4160() { var buf [4160]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4164() { var buf [4164]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4168() { var buf [4168]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4172() { var buf [4172]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4176() { var buf [4176]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4180() { var buf [4180]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4184() { var buf [4184]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4188() { var buf [4188]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4192() { var buf [4192]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4196() { var buf [4196]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4200() { var buf [4200]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4204() { var buf [4204]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4208() { var buf [4208]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4212() { var buf [4212]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4216() { var buf [4216]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4220() { var buf [4220]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4224() { var buf [4224]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4228() { var buf [4228]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4232() { var buf [4232]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4236() { var buf [4236]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4240() { var buf [4240]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4244() { var buf [4244]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4248() { var buf [4248]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4252() { var buf [4252]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4256() { var buf [4256]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4260() { var buf [4260]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4264() { var buf [4264]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4268() { var buf [4268]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4272() { var buf [4272]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4276() { var buf [4276]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4280() { var buf [4280]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4284() { var buf [4284]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4288() { var buf [4288]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4292() { var buf [4292]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4296() { var buf [4296]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4300() { var buf [4300]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4304() { var buf [4304]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4308() { var buf [4308]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4312() { var buf [4312]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4316() { var buf [4316]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4320() { var buf [4320]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4324() { var buf [4324]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4328() { var buf [4328]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4332() { var buf [4332]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4336() { var buf [4336]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4340() { var buf [4340]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4344() { var buf [4344]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4348() { var buf [4348]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4352() { var buf [4352]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4356() { var buf [4356]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4360() { var buf [4360]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4364() { var buf [4364]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4368() { var buf [4368]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4372() { var buf [4372]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4376() { var buf [4376]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4380() { var buf [4380]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4384() { var buf [4384]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4388() { var buf [4388]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4392() { var buf [4392]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4396() { var buf [4396]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4400() { var buf [4400]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4404() { var buf [4404]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4408() { var buf [4408]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4412() { var buf [4412]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4416() { var buf [4416]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4420() { var buf [4420]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4424() { var buf [4424]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4428() { var buf [4428]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4432() { var buf [4432]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4436() { var buf [4436]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4440() { var buf [4440]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4444() { var buf [4444]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4448() { var buf [4448]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4452() { var buf [4452]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4456() { var buf [4456]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4460() { var buf [4460]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4464() { var buf [4464]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4468() { var buf [4468]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4472() { var buf [4472]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4476() { var buf [4476]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4480() { var buf [4480]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4484() { var buf [4484]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4488() { var buf [4488]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4492() { var buf [4492]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4496() { var buf [4496]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4500() { var buf [4500]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4504() { var buf [4504]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4508() { var buf [4508]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4512() { var buf [4512]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4516() { var buf [4516]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4520() { var buf [4520]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4524() { var buf [4524]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4528() { var buf [4528]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4532() { var buf [4532]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4536() { var buf [4536]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4540() { var buf [4540]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4544() { var buf [4544]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4548() { var buf [4548]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4552() { var buf [4552]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4556() { var buf [4556]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4560() { var buf [4560]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4564() { var buf [4564]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4568() { var buf [4568]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4572() { var buf [4572]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4576() { var buf [4576]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4580() { var buf [4580]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4584() { var buf [4584]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4588() { var buf [4588]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4592() { var buf [4592]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4596() { var buf [4596]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4600() { var buf [4600]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4604() { var buf [4604]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4608() { var buf [4608]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4612() { var buf [4612]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4616() { var buf [4616]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4620() { var buf [4620]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4624() { var buf [4624]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4628() { var buf [4628]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4632() { var buf [4632]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4636() { var buf [4636]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4640() { var buf [4640]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4644() { var buf [4644]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4648() { var buf [4648]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4652() { var buf [4652]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4656() { var buf [4656]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4660() { var buf [4660]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4664() { var buf [4664]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4668() { var buf [4668]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4672() { var buf [4672]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4676() { var buf [4676]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4680() { var buf [4680]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4684() { var buf [4684]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4688() { var buf [4688]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4692() { var buf [4692]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4696() { var buf [4696]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4700() { var buf [4700]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4704() { var buf [4704]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4708() { var buf [4708]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4712() { var buf [4712]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4716() { var buf [4716]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4720() { var buf [4720]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4724() { var buf [4724]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4728() { var buf [4728]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4732() { var buf [4732]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4736() { var buf [4736]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4740() { var buf [4740]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4744() { var buf [4744]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4748() { var buf [4748]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4752() { var buf [4752]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4756() { var buf [4756]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4760() { var buf [4760]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4764() { var buf [4764]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4768() { var buf [4768]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4772() { var buf [4772]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4776() { var buf [4776]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4780() { var buf [4780]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4784() { var buf [4784]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4788() { var buf [4788]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4792() { var buf [4792]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4796() { var buf [4796]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4800() { var buf [4800]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4804() { var buf [4804]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4808() { var buf [4808]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4812() { var buf [4812]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4816() { var buf [4816]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4820() { var buf [4820]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4824() { var buf [4824]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4828() { var buf [4828]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4832() { var buf [4832]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4836() { var buf [4836]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4840() { var buf [4840]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4844() { var buf [4844]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4848() { var buf [4848]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4852() { var buf [4852]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4856() { var buf [4856]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4860() { var buf [4860]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4864() { var buf [4864]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4868() { var buf [4868]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4872() { var buf [4872]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4876() { var buf [4876]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4880() { var buf [4880]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4884() { var buf [4884]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4888() { var buf [4888]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4892() { var buf [4892]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4896() { var buf [4896]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4900() { var buf [4900]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4904() { var buf [4904]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4908() { var buf [4908]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4912() { var buf [4912]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4916() { var buf [4916]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4920() { var buf [4920]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4924() { var buf [4924]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4928() { var buf [4928]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4932() { var buf [4932]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4936() { var buf [4936]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4940() { var buf [4940]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4944() { var buf [4944]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4948() { var buf [4948]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4952() { var buf [4952]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4956() { var buf [4956]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4960() { var buf [4960]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4964() { var buf [4964]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4968() { var buf [4968]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4972() { var buf [4972]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4976() { var buf [4976]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4980() { var buf [4980]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4984() { var buf [4984]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4988() { var buf [4988]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4992() { var buf [4992]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4996() { var buf [4996]byte; use(buf[:]); C.callGoStackCheck() }
+func stack5000() { var buf [5000]byte; use(buf[:]); C.callGoStackCheck() }
diff --git a/libgo/misc/cgo/test/callback_c.c b/libgo/misc/cgo/test/callback_c.c
new file mode 100644 (file)
index 0000000..8921b73
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright 2011 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.
+
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "_cgo_export.h"
+
+void
+callback(void *f)
+{
+       // use some stack space
+       volatile char data[64*1024];
+
+       data[0] = 0;
+       goCallback(f);
+        data[sizeof(data)-1] = 0;
+}
+
+void
+callGoFoo(void)
+{
+       extern void goFoo(void);
+       goFoo();
+}
+
+void
+IntoC(void)
+{
+       BackIntoGo();
+}
+
+#ifdef WIN32
+#include <windows.h>
+long long
+mysleep(int seconds) {
+       long long st = GetTickCount();
+       Sleep(1000 * seconds);
+       return st;
+}
+#else
+#include <sys/time.h>
+long long
+mysleep(int seconds) {
+       long long st;
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+       st = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+       sleep(seconds);
+       return st;
+}
+#endif
+
+long long
+twoSleep(int n)
+{
+       BackgroundSleep(n);
+       return mysleep(n);
+}
+
+void
+callGoStackCheck(void)
+{
+       extern void goStackCheck(void);
+       goStackCheck();
+}
+
+int
+returnAfterGrow(void)
+{
+       extern int goReturnVal(void);
+       goReturnVal();
+       return 123456;
+}
+
+int
+returnAfterGrowFromGo(void)
+{
+       extern int goReturnVal(void);
+       return goReturnVal();
+}
+
+void
+callGoWithString(void)
+{
+       extern void goWithString(GoString);
+       const char *str = "string passed from C to Go";
+       goWithString((GoString){str, strlen(str)});
+}
diff --git a/libgo/misc/cgo/test/callback_c_gc.c b/libgo/misc/cgo/test/callback_c_gc.c
new file mode 100644 (file)
index 0000000..eb720eb
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2013 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 gc
+
+#include "_cgo_export.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Test calling panic from C.  This is what SWIG does.  */
+
+extern void crosscall2(void (*fn)(void *, int), void *, int);
+extern void _cgo_panic(void *, int);
+extern void _cgo_allocate(void *, int);
+
+void
+callPanic(void)
+{
+       struct { const char *p; } a;
+       a.p = "panic from C";
+       crosscall2(_cgo_panic, &a, sizeof a);
+       *(int*)1 = 1;
+}
diff --git a/libgo/misc/cgo/test/callback_c_gccgo.c b/libgo/misc/cgo/test/callback_c_gccgo.c
new file mode 100644 (file)
index 0000000..4eaa818
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2013 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 gccgo
+
+#include "_cgo_export.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Test calling panic from C.  This is what SWIG does.  */
+
+extern void _cgo_panic(const char *);
+extern void *_cgo_allocate(size_t);
+
+void
+callPanic(void)
+{
+       _cgo_panic("panic from C");
+}
diff --git a/libgo/misc/cgo/test/cflags.go b/libgo/misc/cgo/test/cflags.go
new file mode 100644 (file)
index 0000000..bc290bf
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2013 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.
+
+// Test that the #cgo CFLAGS directive works,
+// with and without platform filters.
+// See https://golang.org/issue/5224 for details.
+package cgotest
+
+/*
+#cgo CFLAGS: -DCOMMON_VALUE=123
+#cgo windows CFLAGS: -DIS_WINDOWS=1
+#cgo !windows CFLAGS: -DIS_WINDOWS=0
+int common = COMMON_VALUE;
+int is_windows = IS_WINDOWS;
+*/
+import "C"
+
+import (
+       "runtime"
+       "testing"
+)
+
+func testCflags(t *testing.T) {
+       is_windows := C.is_windows == 1
+       if is_windows != (runtime.GOOS == "windows") {
+               t.Errorf("is_windows: %v, runtime.GOOS: %s", is_windows, runtime.GOOS)
+       }
+       if C.common != 123 {
+               t.Errorf("common: %v (expected 123)", C.common)
+       }
+}
diff --git a/libgo/misc/cgo/test/cgo_linux_test.go b/libgo/misc/cgo/test/cgo_linux_test.go
new file mode 100644 (file)
index 0000000..9c15f69
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2012 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.
+
+package cgotest
+
+import "testing"
+
+func TestSetgid(t *testing.T)  { testSetgid(t) }
+func Test6997(t *testing.T)    { test6997(t) }
+func TestBuildID(t *testing.T) { testBuildID(t) }
+func Test9400(t *testing.T)    { test9400(t) }
diff --git a/libgo/misc/cgo/test/cgo_stubs_android_test.go b/libgo/misc/cgo/test/cgo_stubs_android_test.go
new file mode 100644 (file)
index 0000000..710e094
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2012 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.
+
+package cgotest
+
+import "testing"
+
+// Stubs for tests that fails to build on Android
+func test6997(t *testing.T)        {}
+func test3775(t *testing.T)        {}
+func test8694(t *testing.T)        {}
+func testSigaltstack(t *testing.T) {}
diff --git a/libgo/misc/cgo/test/cgo_test.go b/libgo/misc/cgo/test/cgo_test.go
new file mode 100644 (file)
index 0000000..a6de999
--- /dev/null
@@ -0,0 +1,80 @@
+// Copyright 2011 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.
+
+package cgotest
+
+import "testing"
+
+// The actual test functions are in non-_test.go files
+// so that they can use cgo (import "C").
+// These wrappers are here for gotest to find.
+
+func TestAlign(t *testing.T)                 { testAlign(t) }
+func TestConst(t *testing.T)                 { testConst(t) }
+func TestEnum(t *testing.T)                  { testEnum(t) }
+func TestAtol(t *testing.T)                  { testAtol(t) }
+func TestErrno(t *testing.T)                 { testErrno(t) }
+func TestMultipleAssign(t *testing.T)        { testMultipleAssign(t) }
+func TestUnsignedInt(t *testing.T)           { testUnsignedInt(t) }
+func TestCallback(t *testing.T)              { testCallback(t) }
+func TestCallbackGC(t *testing.T)            { testCallbackGC(t) }
+func TestCallbackPanic(t *testing.T)         { testCallbackPanic(t) }
+func TestCallbackPanicLoop(t *testing.T)     { testCallbackPanicLoop(t) }
+func TestCallbackPanicLocked(t *testing.T)   { testCallbackPanicLocked(t) }
+func TestPanicFromC(t *testing.T)            { testPanicFromC(t) }
+func TestZeroArgCallback(t *testing.T)       { testZeroArgCallback(t) }
+func TestBlocking(t *testing.T)              { testBlocking(t) }
+func Test1328(t *testing.T)                  { test1328(t) }
+func TestParallelSleep(t *testing.T)         { testParallelSleep(t) }
+func TestSetEnv(t *testing.T)                { testSetEnv(t) }
+func TestHelpers(t *testing.T)               { testHelpers(t) }
+func TestLibgcc(t *testing.T)                { testLibgcc(t) }
+func Test1635(t *testing.T)                  { test1635(t) }
+func TestPrintf(t *testing.T)                { testPrintf(t) }
+func Test4029(t *testing.T)                  { test4029(t) }
+func TestBoolAlign(t *testing.T)             { testBoolAlign(t) }
+func Test3729(t *testing.T)                  { test3729(t) }
+func Test3775(t *testing.T)                  { test3775(t) }
+func TestCthread(t *testing.T)               { testCthread(t) }
+func TestCallbackCallers(t *testing.T)       { testCallbackCallers(t) }
+func Test5227(t *testing.T)                  { test5227(t) }
+func TestCflags(t *testing.T)                { testCflags(t) }
+func Test5337(t *testing.T)                  { test5337(t) }
+func Test5548(t *testing.T)                  { test5548(t) }
+func Test5603(t *testing.T)                  { test5603(t) }
+func Test6833(t *testing.T)                  { test6833(t) }
+func Test3250(t *testing.T)                  { test3250(t) }
+func TestCallbackStack(t *testing.T)         { testCallbackStack(t) }
+func TestFpVar(t *testing.T)                 { testFpVar(t) }
+func Test4339(t *testing.T)                  { test4339(t) }
+func Test6390(t *testing.T)                  { test6390(t) }
+func Test5986(t *testing.T)                  { test5986(t) }
+func Test7665(t *testing.T)                  { test7665(t) }
+func TestNaming(t *testing.T)                { testNaming(t) }
+func Test7560(t *testing.T)                  { test7560(t) }
+func Test5242(t *testing.T)                  { test5242(t) }
+func Test8092(t *testing.T)                  { test8092(t) }
+func Test7978(t *testing.T)                  { test7978(t) }
+func Test8694(t *testing.T)                  { test8694(t) }
+func Test8517(t *testing.T)                  { test8517(t) }
+func Test8811(t *testing.T)                  { test8811(t) }
+func TestReturnAfterGrow(t *testing.T)       { testReturnAfterGrow(t) }
+func TestReturnAfterGrowFromGo(t *testing.T) { testReturnAfterGrowFromGo(t) }
+func Test9026(t *testing.T)                  { test9026(t) }
+func Test9510(t *testing.T)                  { test9510(t) }
+func Test9557(t *testing.T)                  { test9557(t) }
+func Test10303(t *testing.T)                 { test10303(t, 10) }
+func Test11925(t *testing.T)                 { test11925(t) }
+func Test12030(t *testing.T)                 { test12030(t) }
+func TestGCC68255(t *testing.T)              { testGCC68255(t) }
+func TestCallGoWithString(t *testing.T)      { testCallGoWithString(t) }
+func Test14838(t *testing.T)                 { test14838(t) }
+func Test8756(t *testing.T)                  { test8756(t) }
+func Test17065(t *testing.T)                 { test17065(t) }
+func TestThreadLock(t *testing.T)            { testThreadLockFunc(t) }
+func TestCheckConst(t *testing.T)            { testCheckConst(t) }
+func Test17537(t *testing.T)                 { test17537(t) }
+func Test18126(t *testing.T)                 { test18126(t) }
+
+func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
diff --git a/libgo/misc/cgo/test/cgo_thread_lock.go b/libgo/misc/cgo/test/cgo_thread_lock.go
new file mode 100644 (file)
index 0000000..b105068
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright 2016 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 linux,freebsd,openbsd
+
+package cgotest
+
+/*
+#include <unistd.h>
+#include <sys/syscall.h>
+void Gosched(void);
+static int Ctid(void) { Gosched(); return syscall(SYS_gettid); }
+*/
+import "C"
+
+import (
+       "runtime"
+       "syscall"
+       "testing"
+       "time"
+)
+
+//export Gosched
+func Gosched() {
+       runtime.Gosched()
+}
+
+func init() {
+       testThreadLockFunc = testThreadLock
+}
+
+func testThreadLock(t *testing.T) {
+       stop := make(chan int)
+       go func() {
+               // We need the G continue running,
+               // so the M has a chance to run this G.
+               for {
+                       select {
+                       case <-stop:
+                               return
+                       case <-time.After(time.Millisecond * 100):
+                       }
+               }
+       }()
+       defer close(stop)
+
+       for i := 0; i < 1000; i++ {
+               if C.int(syscall.Gettid()) != C.Ctid() {
+                       t.Fatalf("cgo has not locked OS thread")
+               }
+       }
+}
diff --git a/libgo/misc/cgo/test/cgo_unix_test.go b/libgo/misc/cgo/test/cgo_unix_test.go
new file mode 100644 (file)
index 0000000..e3d5916
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2015 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 !windows
+
+package cgotest
+
+import "testing"
+
+func TestSigaltstack(t *testing.T) { testSigaltstack(t) }
+func TestSigprocmask(t *testing.T) { testSigprocmask(t) }
+func Test18146(t *testing.T)       { test18146(t) }
diff --git a/libgo/misc/cgo/test/checkconst.go b/libgo/misc/cgo/test/checkconst.go
new file mode 100644 (file)
index 0000000..0160c1e
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2016 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.
+
+// Test a constant in conjunction with pointer checking.
+
+package cgotest
+
+/*
+#include <stdlib.h>
+
+#define CheckConstVal 0
+
+typedef struct {
+       int *p;
+} CheckConstStruct;
+
+static void CheckConstFunc(CheckConstStruct *p, int e) {
+}
+*/
+import "C"
+
+import (
+       "testing"
+       "unsafe"
+)
+
+func testCheckConst(t *testing.T) {
+       // The test is that this compiles successfully.
+       p := C.malloc(C.size_t(unsafe.Sizeof(C.int(0))))
+       defer C.free(p)
+       C.CheckConstFunc(&C.CheckConstStruct{(*C.int)(p)}, C.CheckConstVal)
+}
diff --git a/libgo/misc/cgo/test/complex.go b/libgo/misc/cgo/test/complex.go
new file mode 100644 (file)
index 0000000..ca0a97d
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2016 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.
+
+package cgotest
+
+/*
+struct {
+       float x;
+       _Complex float y;
+} cplxAlign = { 3.14, 2.17 };
+*/
+import "C"
+
+import "testing"
+
+func TestComplexAlign(t *testing.T) {
+       if C.cplxAlign.x != 3.14 {
+               t.Errorf("got %v, expected 3.14", C.cplxAlign.x)
+       }
+       if C.cplxAlign.y != 2.17 {
+               t.Errorf("got %v, expected 2.17", C.cplxAlign.y)
+       }
+}
diff --git a/libgo/misc/cgo/test/cthread.go b/libgo/misc/cgo/test/cthread.go
new file mode 100644 (file)
index 0000000..af44911
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2013 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.
+
+package cgotest
+
+// extern void doAdd(int, int);
+import "C"
+
+import (
+       "runtime"
+       "sync"
+       "testing"
+)
+
+var sum struct {
+       sync.Mutex
+       i int
+}
+
+//export Add
+func Add(x int) {
+       defer func() {
+               recover()
+       }()
+       sum.Lock()
+       sum.i += x
+       sum.Unlock()
+       var p *int
+       *p = 2
+}
+
+func testCthread(t *testing.T) {
+       if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
+               t.Skip("the iOS exec wrapper is unable to properly handle the panic from Add")
+       }
+       sum.i = 0
+       C.doAdd(10, 6)
+
+       want := 10 * (10 - 1) / 2 * 6
+       if sum.i != want {
+               t.Fatalf("sum=%d, want %d", sum.i, want)
+       }
+}
diff --git a/libgo/misc/cgo/test/cthread_unix.c b/libgo/misc/cgo/test/cthread_unix.c
new file mode 100644 (file)
index 0000000..6323e49
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2013 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 darwin dragonfly freebsd linux netbsd openbsd solaris
+
+#include <pthread.h>
+#include "_cgo_export.h"
+
+static void*
+addThread(void *p)
+{
+       int i, max;
+       
+       max = *(int*)p;
+       for(i=0; i<max; i++)
+               Add(i);
+       return 0;
+}
+
+void
+doAdd(int max, int nthread)
+{
+       enum { MaxThread = 20 };
+       int i;
+       pthread_t thread_id[MaxThread];
+       
+       if(nthread > MaxThread)
+               nthread = MaxThread;
+       for(i=0; i<nthread; i++)
+               pthread_create(&thread_id[i], 0, addThread, &max);
+       for(i=0; i<nthread; i++)
+               pthread_join(thread_id[i], 0);          
+}
diff --git a/libgo/misc/cgo/test/cthread_windows.c b/libgo/misc/cgo/test/cthread_windows.c
new file mode 100644 (file)
index 0000000..3a62ddd
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2013 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.
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <process.h>
+#include "_cgo_export.h"
+
+__stdcall
+static unsigned int
+addThread(void *p)
+{
+       int i, max;
+       
+       max = *(int*)p;
+       for(i=0; i<max; i++)
+               Add(i);
+       return 0;
+}
+
+void
+doAdd(int max, int nthread)
+{
+       enum { MaxThread = 20 };
+       int i;
+       uintptr_t thread_id[MaxThread];
+       
+       if(nthread > MaxThread)
+               nthread = MaxThread;
+       for(i=0; i<nthread; i++)
+               thread_id[i] = _beginthreadex(0, 0, addThread, &max, 0, 0);
+       for(i=0; i<nthread; i++) {
+               WaitForSingleObject((HANDLE)thread_id[i], INFINITE);
+               CloseHandle((HANDLE)thread_id[i]);
+       }
+}
diff --git a/libgo/misc/cgo/test/duplicate_symbol.go b/libgo/misc/cgo/test/duplicate_symbol.go
new file mode 100644 (file)
index 0000000..6144271
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2010 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.
+
+// This file contains test cases for cgo.
+
+package cgotest
+
+/*
+int base_symbol = 0;
+
+#define alias_one base_symbol
+#define alias_two base_symbol
+*/
+import "C"
+
+import "fmt"
+
+func duplicateSymbols() {
+       fmt.Printf("%v %v %v\n", C.base_symbol, C.alias_one, C.alias_two)
+}
diff --git a/libgo/misc/cgo/test/env.go b/libgo/misc/cgo/test/env.go
new file mode 100644 (file)
index 0000000..b2081b7
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2011 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.
+
+package cgotest
+
+/*
+#include <stdlib.h>
+*/
+import "C"
+import (
+       "os"
+       "runtime"
+       "testing"
+       "unsafe"
+)
+
+// This is really an os package test but here for convenience.
+func testSetEnv(t *testing.T) {
+       if runtime.GOOS == "windows" {
+               // Go uses SetEnvironmentVariable on windows. Howerver,
+               // C runtime takes a *copy* at process startup of thei
+               // OS environment, and stores it in environ/envp.
+               // It is this copy that getenv/putenv manipulate.
+               t.Logf("skipping test")
+               return
+       }
+       const key = "CGO_OS_TEST_KEY"
+       const val = "CGO_OS_TEST_VALUE"
+       os.Setenv(key, val)
+       keyc := C.CString(key)
+       defer C.free(unsafe.Pointer(keyc))
+       v := C.getenv(keyc)
+       if uintptr(unsafe.Pointer(v)) == 0 {
+               t.Fatal("getenv returned NULL")
+       }
+       vs := C.GoString(v)
+       if vs != val {
+               t.Fatalf("getenv() = %q; want %q", vs, val)
+       }
+}
diff --git a/libgo/misc/cgo/test/exports.go b/libgo/misc/cgo/test/exports.go
new file mode 100644 (file)
index 0000000..71e5dcd
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2011 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.
+
+package cgotest
+
+import "C"
+import "runtime"
+
+//export ReturnIntLong
+func ReturnIntLong() (int, C.long) {
+       return 1, 2
+}
+
+//export gc
+func gc() {
+       runtime.GC()
+}
diff --git a/libgo/misc/cgo/test/fpvar.go b/libgo/misc/cgo/test/fpvar.go
new file mode 100644 (file)
index 0000000..7aab8ca
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2013 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.
+
+// This file contains test cases for cgo with function pointer variables.
+
+package cgotest
+
+/*
+typedef int (*intFunc) ();
+
+int
+bridge_int_func(intFunc f)
+{
+       return f();
+}
+
+int fortytwo()
+{
+       return 42;
+}
+
+*/
+import "C"
+import "testing"
+
+func callBridge(f C.intFunc) int {
+       return int(C.bridge_int_func(f))
+}
+
+func callCBridge(f C.intFunc) C.int {
+       return C.bridge_int_func(f)
+}
+
+func testFpVar(t *testing.T) {
+       const expected = 42
+       f := C.intFunc(C.fortytwo)
+       res1 := C.bridge_int_func(f)
+       if r1 := int(res1); r1 != expected {
+               t.Errorf("got %d, want %d", r1, expected)
+       }
+       res2 := callCBridge(f)
+       if r2 := int(res2); r2 != expected {
+               t.Errorf("got %d, want %d", r2, expected)
+       }
+       r3 := callBridge(f)
+       if r3 != expected {
+               t.Errorf("got %d, want %d", r3, expected)
+       }
+}
diff --git a/libgo/misc/cgo/test/gcc68255.go b/libgo/misc/cgo/test/gcc68255.go
new file mode 100644 (file)
index 0000000..23e103d
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2015 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.
+
+package cgotest
+
+import (
+       "testing"
+
+       "./gcc68255"
+)
+
+func testGCC68255(t *testing.T) {
+       if !gcc68255.F() {
+               t.Error("C global variable was not initialized")
+       }
+}
diff --git a/libgo/misc/cgo/test/gcc68255/a.go b/libgo/misc/cgo/test/gcc68255/a.go
new file mode 100644 (file)
index 0000000..e106dee
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2015 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.
+
+// Test that it's OK to have C code that does nothing other than
+// initialize a global variable.  This used to fail with gccgo.
+
+package gcc68255
+
+/*
+#include "c.h"
+*/
+import "C"
+
+func F() bool {
+       return C.v != nil
+}
diff --git a/libgo/misc/cgo/test/gcc68255/c.c b/libgo/misc/cgo/test/gcc68255/c.c
new file mode 100644 (file)
index 0000000..a4fe193
--- /dev/null
@@ -0,0 +1,8 @@
+// Copyright 2015 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.
+
+static void f(void) {
+}
+
+void (*v)(void) = f;
diff --git a/libgo/misc/cgo/test/gcc68255/c.h b/libgo/misc/cgo/test/gcc68255/c.h
new file mode 100644 (file)
index 0000000..05ecd81
--- /dev/null
@@ -0,0 +1,5 @@
+// Copyright 2015 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.
+
+extern void (*v)(void);
diff --git a/libgo/misc/cgo/test/helpers.go b/libgo/misc/cgo/test/helpers.go
new file mode 100644 (file)
index 0000000..f6a822a
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2011 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.
+
+package cgotest
+
+// const char *greeting = "hello, world";
+import "C"
+
+import (
+       "reflect"
+       "testing"
+       "unsafe"
+)
+
+const greeting = "hello, world"
+
+type testPair struct {
+       Name      string
+       Got, Want interface{}
+}
+
+var testPairs = []testPair{
+       {"GoString", C.GoString(C.greeting), greeting},
+       {"GoStringN", C.GoStringN(C.greeting, 5), greeting[:5]},
+       {"GoBytes", C.GoBytes(unsafe.Pointer(C.greeting), 5), []byte(greeting[:5])},
+}
+
+func testHelpers(t *testing.T) {
+       for _, pair := range testPairs {
+               if !reflect.DeepEqual(pair.Got, pair.Want) {
+                       t.Errorf("%s: got %#v, want %#v", pair.Name, pair.Got, pair.Want)
+               }
+       }
+}
diff --git a/libgo/misc/cgo/test/issue10303.go b/libgo/misc/cgo/test/issue10303.go
new file mode 100644 (file)
index 0000000..66e2644
--- /dev/null
@@ -0,0 +1,76 @@
+// Copyright 2015 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.
+
+// Issue 10303. Pointers passed to C were not marked as escaping (bug in cgo).
+
+package cgotest
+
+import "runtime"
+
+/*
+typedef int *intptr;
+
+void setintstar(int *x) {
+       *x = 1;
+}
+
+void setintptr(intptr x) {
+       *x = 1;
+}
+
+void setvoidptr(void *x) {
+       *(int*)x = 1;
+}
+
+typedef struct Struct Struct;
+struct Struct {
+       int *P;
+};
+
+void setstruct(Struct s) {
+       *s.P = 1;
+}
+
+*/
+import "C"
+
+import (
+       "testing"
+       "unsafe"
+)
+
+func test10303(t *testing.T, n int) {
+       if runtime.Compiler == "gccgo" {
+               t.Skip("gccgo permits C pointers on the stack")
+       }
+
+       // Run at a few different stack depths just to avoid an unlucky pass
+       // due to variables ending up on different pages.
+       if n > 0 {
+               test10303(t, n-1)
+       }
+       if t.Failed() {
+               return
+       }
+       var x, y, z, v, si C.int
+       var s C.Struct
+       C.setintstar(&x)
+       C.setintptr(&y)
+       C.setvoidptr(unsafe.Pointer(&v))
+       s.P = &si
+       C.setstruct(s)
+
+       if uintptr(unsafe.Pointer(&x))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff {
+               t.Error("C int* argument on stack")
+       }
+       if uintptr(unsafe.Pointer(&y))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff {
+               t.Error("C intptr argument on stack")
+       }
+       if uintptr(unsafe.Pointer(&v))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff {
+               t.Error("C void* argument on stack")
+       }
+       if uintptr(unsafe.Pointer(&si))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff {
+               t.Error("C struct field pointer on stack")
+       }
+}
diff --git a/libgo/misc/cgo/test/issue11925.go b/libgo/misc/cgo/test/issue11925.go
new file mode 100644 (file)
index 0000000..c5c8a26
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2015 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.
+
+// Issue 11925.  Structs with zero-length trailing fields are now
+// padded by the Go compiler.
+
+package cgotest
+
+/*
+struct a11925 {
+       int i;
+       char a[0];
+       char b[0];
+};
+
+struct b11925 {
+       int i;
+       char a[0];
+       char b[];
+};
+*/
+import "C"
+
+import (
+       "testing"
+       "unsafe"
+)
+
+func test11925(t *testing.T) {
+       if C.sizeof_struct_a11925 != unsafe.Sizeof(C.struct_a11925{}) {
+               t.Errorf("size of a changed: C %d, Go %d", C.sizeof_struct_a11925, unsafe.Sizeof(C.struct_a11925{}))
+       }
+       if C.sizeof_struct_b11925 != unsafe.Sizeof(C.struct_b11925{}) {
+               t.Errorf("size of b changed: C %d, Go %d", C.sizeof_struct_b11925, unsafe.Sizeof(C.struct_b11925{}))
+       }
+}
diff --git a/libgo/misc/cgo/test/issue12030.go b/libgo/misc/cgo/test/issue12030.go
new file mode 100644 (file)
index 0000000..f863c58
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2015 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.
+
+// Issue 12030. sprintf is defined in both ntdll and msvcrt,
+// Normally we want the one in the msvcrt.
+
+package cgotest
+
+/*
+#include <stdio.h>
+#include <stdlib.h>
+void issue12030conv(char *buf, double x) {
+       sprintf(buf, "d=%g", x);
+}
+*/
+import "C"
+
+import (
+       "fmt"
+       "testing"
+       "unsafe"
+)
+
+func test12030(t *testing.T) {
+       buf := (*C.char)(C.malloc(256))
+       defer C.free(unsafe.Pointer(buf))
+       for _, f := range []float64{1.0, 2.0, 3.14} {
+               C.issue12030conv(buf, C.double(f))
+               got := C.GoString(buf)
+               if want := fmt.Sprintf("d=%g", f); got != want {
+                       t.Fatalf("C.sprintf failed for %g: %q != %q", f, got, want)
+               }
+       }
+}
diff --git a/libgo/misc/cgo/test/issue1222.go b/libgo/misc/cgo/test/issue1222.go
new file mode 100644 (file)
index 0000000..4868da8
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2010 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.
+
+// This file contains test cases for cgo.
+
+package cgotest
+
+/*
+// issue 1222
+typedef union {
+       long align;
+} xxpthread_mutex_t;
+
+struct ibv_async_event {
+       union {
+               int x;
+       } element;
+};
+
+struct ibv_context {
+       xxpthread_mutex_t mutex;
+};
+*/
+import "C"
+
+type AsyncEvent struct {
+       event C.struct_ibv_async_event
+}
diff --git a/libgo/misc/cgo/test/issue1328.go b/libgo/misc/cgo/test/issue1328.go
new file mode 100644 (file)
index 0000000..2401c10
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2011 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.
+
+package cgotest
+
+import "testing"
+
+// extern void BackIntoGo(void);
+// void IntoC(void);
+import "C"
+
+//export BackIntoGo
+func BackIntoGo() {
+       x := 1
+
+       for i := 0; i < 10000; i++ {
+               xvariadic(x)
+               if x != 1 {
+                       panic("x is not 1?")
+               }
+       }
+}
+
+func xvariadic(x ...interface{}) {
+}
+
+func test1328(t *testing.T) {
+       C.IntoC()
+}
diff --git a/libgo/misc/cgo/test/issue13402.go b/libgo/misc/cgo/test/issue13402.go
new file mode 100644 (file)
index 0000000..3af24c2
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2015 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.
+
+package cgotest
+
+import "C"
+
+var _ C.complexfloat
+var _ C.complexdouble
diff --git a/libgo/misc/cgo/test/issue13930.go b/libgo/misc/cgo/test/issue13930.go
new file mode 100644 (file)
index 0000000..c4a08ee
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2016 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.
+
+// Issue 13930.  Test that cgo's multiple-value special form for
+// C function calls works in variable declaration statements.
+
+package cgotest
+
+// #include <stdlib.h>
+import "C"
+
+var _, _ = C.abs(0)
diff --git a/libgo/misc/cgo/test/issue14838.go b/libgo/misc/cgo/test/issue14838.go
new file mode 100644 (file)
index 0000000..c8e1681
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2016 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.
+
+// Issue 14838. add CBytes function
+
+package cgotest
+
+/*
+#include <stdlib.h>
+
+int check_cbytes(char *b, size_t l) {
+       int i;
+       for (i = 0; i < l; i++) {
+               if (b[i] != i) {
+                       return 0;
+               }
+       }
+       return 1;
+}
+*/
+import "C"
+
+import (
+       "testing"
+       "unsafe"
+)
+
+func test14838(t *testing.T) {
+       data := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
+       cData := C.CBytes(data)
+       defer C.free(cData)
+
+       if C.check_cbytes((*C.char)(cData), C.size_t(len(data))) == 0 {
+               t.Fatalf("mismatched data: expected %v, got %v", data, (*(*[10]byte)(unsafe.Pointer(cData)))[:])
+       }
+}
diff --git a/libgo/misc/cgo/test/issue1560.go b/libgo/misc/cgo/test/issue1560.go
new file mode 100644 (file)
index 0000000..30f6152
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2011 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.
+
+package cgotest
+
+/*
+// mysleep returns the absolute start time in ms.
+long long mysleep(int seconds);
+
+// twoSleep returns the absolute start time of the first sleep
+// in ms.
+long long twoSleep(int);
+*/
+import "C"
+
+import (
+       "testing"
+       "time"
+)
+
+var sleepDone = make(chan int64)
+
+// parallelSleep returns the absolute difference between the start time
+// of the two sleeps.
+func parallelSleep(n int) int64 {
+       t := int64(C.twoSleep(C.int(n))) - <-sleepDone
+       if t < 0 {
+               return -t
+       }
+       return t
+}
+
+//export BackgroundSleep
+func BackgroundSleep(n int32) {
+       go func() {
+               sleepDone <- int64(C.mysleep(C.int(n)))
+       }()
+}
+
+func testParallelSleep(t *testing.T) {
+       sleepSec := 1
+       dt := time.Duration(parallelSleep(sleepSec)) * time.Millisecond
+       t.Logf("difference in start time for two sleep(%d) is %v", sleepSec, dt)
+       // bug used to run sleeps in serial, producing a 2*sleepSec-second delay.
+       // we detect if the start times of those sleeps are > 0.5*sleepSec-second.
+       if dt >= time.Duration(sleepSec)*time.Second/2 {
+               t.Fatalf("parallel %d-second sleeps slept for %f seconds", sleepSec, dt.Seconds())
+       }
+}
diff --git a/libgo/misc/cgo/test/issue1635.go b/libgo/misc/cgo/test/issue1635.go
new file mode 100644 (file)
index 0000000..2589927
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2012 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.
+
+package cgotest
+
+/*
+// Mac OS X's gcc will generate scattered relocation 2/1 for
+// this function on Darwin/386, and 8l couldn't handle it.
+// this example is in issue 1635
+#include <stdio.h>
+void scatter() {
+       void *p = scatter;
+       printf("scatter = %p\n", p);
+}
+
+// Adding this explicit extern declaration makes this a test for
+// https://gcc.gnu.org/PR68072 aka https://golang.org/issue/13344 .
+// It used to cause a cgo error when building with GCC 6.
+extern int hola;
+
+// this example is in issue 3253
+int hola = 0;
+int testHola() { return hola; }
+*/
+import "C"
+
+import "testing"
+
+func test1635(t *testing.T) {
+       C.scatter()
+       if v := C.hola; v != 0 {
+               t.Fatalf("C.hola is %d, should be 0", v)
+       }
+       if v := C.testHola(); v != 0 {
+               t.Fatalf("C.testHola() is %d, should be 0", v)
+       }
+}
diff --git a/libgo/misc/cgo/test/issue17065.go b/libgo/misc/cgo/test/issue17065.go
new file mode 100644 (file)
index 0000000..ede30bc
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2016 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.
+
+package cgotest
+
+/*
+// Test that C symbols larger than a page play nicely with the race detector.
+// See issue 17065.
+
+int ii[65537];
+*/
+import "C"
+
+import (
+       "runtime"
+       "testing"
+)
+
+var sink C.int
+
+func test17065(t *testing.T) {
+       if runtime.GOOS == "darwin" {
+               t.Skip("broken on darwin; issue 17065")
+       }
+       for i := range C.ii {
+               sink = C.ii[i]
+       }
+}
diff --git a/libgo/misc/cgo/test/issue17537.go b/libgo/misc/cgo/test/issue17537.go
new file mode 100644 (file)
index 0000000..777104e
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright 2016 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.
+
+// Issue 17537.  The void* cast introduced by cgo to avoid problems
+// with const/volatile qualifiers breaks C preprocessor macros that
+// emulate functions.
+
+package cgotest
+
+/*
+#include <stdlib.h>
+
+typedef struct {
+       int i;
+} S17537;
+
+int I17537(S17537 *p);
+
+#define I17537(p) ((p)->i)
+
+// Calling this function used to fail without the cast.
+const int F17537(const char **p) {
+       return **p;
+}
+
+// Calling this function used to trigger an error from the C compiler
+// (issue 18298).
+void F18298(const void *const *p) {
+}
+
+// Test that conversions between typedefs work as they used to.
+typedef const void *T18298_1;
+struct S18298 { int i; };
+typedef const struct S18298 *T18298_2;
+void G18298(T18298_1 t) {
+}
+*/
+import "C"
+
+import "testing"
+
+func test17537(t *testing.T) {
+       v := C.S17537{i: 17537}
+       if got, want := C.I17537(&v), C.int(17537); got != want {
+               t.Errorf("got %d, want %d", got, want)
+       }
+
+       p := (*C.char)(C.malloc(1))
+       *p = 17
+       if got, want := C.F17537(&p), C.int(17); got != want {
+               t.Errorf("got %d, want %d", got, want)
+       }
+
+       C.F18298(nil)
+       var v18298 C.T18298_2
+       C.G18298(C.T18298_1(v18298))
+}
diff --git a/libgo/misc/cgo/test/issue18126.go b/libgo/misc/cgo/test/issue18126.go
new file mode 100644 (file)
index 0000000..ac94a66
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+// Issue 18126: cgo check of void function returning errno.
+
+package cgotest
+
+/*
+#include <stdlib.h>
+
+void Issue18126C(void **p) {
+}
+*/
+import "C"
+
+import (
+       "testing"
+)
+
+func test18126(t *testing.T) {
+       p := C.malloc(1)
+       _, err := C.Issue18126C(&p)
+       C.free(p)
+       _ = err
+}
diff --git a/libgo/misc/cgo/test/issue18146.go b/libgo/misc/cgo/test/issue18146.go
new file mode 100644 (file)
index 0000000..3c60046
--- /dev/null
@@ -0,0 +1,128 @@
+// Copyright 2016 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 !windows
+
+// Issue 18146: pthread_create failure during syscall.Exec.
+
+package cgotest
+
+import "C"
+
+import (
+       "bytes"
+       "crypto/md5"
+       "os"
+       "os/exec"
+       "runtime"
+       "syscall"
+       "testing"
+       "time"
+)
+
+func test18146(t *testing.T) {
+       if runtime.GOOS == "darwin" {
+               t.Skipf("skipping flaky test on %s; see golang.org/issue/18202", runtime.GOOS)
+       }
+
+       if runtime.GOARCH == "mips" || runtime.GOARCH == "mips64" {
+               t.Skipf("skipping on %s", runtime.GOARCH)
+       }
+
+       attempts := 1000
+       threads := 4
+
+       if testing.Short() {
+               attempts = 100
+       }
+
+       // Restrict the number of attempts based on RLIMIT_NPROC.
+       // Tediously, RLIMIT_NPROC was left out of the syscall package,
+       // probably because it is not in POSIX.1, so we define it here.
+       // It is not defined on Solaris.
+       var nproc int
+       setNproc := true
+       switch runtime.GOOS {
+       default:
+               setNproc = false
+       case "linux":
+               nproc = 6
+       case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd":
+               nproc = 7
+       }
+       if setNproc {
+               var rlim syscall.Rlimit
+               if syscall.Getrlimit(nproc, &rlim) == nil {
+                       max := int(rlim.Cur) / (threads + 5)
+                       if attempts > max {
+                               t.Logf("lowering attempts from %d to %d for RLIMIT_NPROC", attempts, max)
+                               attempts = max
+                       }
+               }
+       }
+
+       if os.Getenv("test18146") == "exec" {
+               runtime.GOMAXPROCS(1)
+               for n := threads; n > 0; n-- {
+                       go func() {
+                               for {
+                                       _ = md5.Sum([]byte("Hello, ï €!"))
+                               }
+                       }()
+               }
+               runtime.GOMAXPROCS(threads)
+               argv := append(os.Args, "-test.run=NoSuchTestExists")
+               if err := syscall.Exec(os.Args[0], argv, os.Environ()); err != nil {
+                       t.Fatal(err)
+               }
+       }
+
+       var cmds []*exec.Cmd
+       defer func() {
+               for _, cmd := range cmds {
+                       cmd.Process.Kill()
+               }
+       }()
+
+       args := append(append([]string(nil), os.Args[1:]...), "-test.run=Test18146")
+       for n := attempts; n > 0; n-- {
+               cmd := exec.Command(os.Args[0], args...)
+               cmd.Env = append(os.Environ(), "test18146=exec")
+               buf := bytes.NewBuffer(nil)
+               cmd.Stdout = buf
+               cmd.Stderr = buf
+               if err := cmd.Start(); err != nil {
+                       // We are starting so many processes that on
+                       // some systems (problem seen on Darwin,
+                       // Dragonfly, OpenBSD) the fork call will fail
+                       // with EAGAIN.
+                       if pe, ok := err.(*os.PathError); ok {
+                               err = pe.Err
+                       }
+                       if se, ok := err.(syscall.Errno); ok && (se == syscall.EAGAIN || se == syscall.EMFILE) {
+                               time.Sleep(time.Millisecond)
+                               continue
+                       }
+
+                       t.Error(err)
+                       return
+               }
+               cmds = append(cmds, cmd)
+       }
+
+       failures := 0
+       for _, cmd := range cmds {
+               err := cmd.Wait()
+               if err == nil {
+                       continue
+               }
+
+               t.Errorf("syscall.Exec failed: %v\n%s", err, cmd.Stdout)
+               failures++
+       }
+
+       if failures > 0 {
+               t.Logf("Failed %v of %v attempts.", failures, len(cmds))
+       }
+}
diff --git a/libgo/misc/cgo/test/issue2462.go b/libgo/misc/cgo/test/issue2462.go
new file mode 100644 (file)
index 0000000..febca1e
--- /dev/null
@@ -0,0 +1,102 @@
+// Copyright 2011 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.
+
+package cgotest
+
+import "C"
+
+//export exportbyte
+func exportbyte() byte {
+       return 0
+}
+
+//export exportbool
+func exportbool() bool {
+       return false
+}
+
+//export exportrune
+func exportrune() rune {
+       return 0
+}
+
+//export exporterror
+func exporterror() error {
+       return nil
+}
+
+//export exportint
+func exportint() int {
+       return 0
+}
+
+//export exportuint
+func exportuint() uint {
+       return 0
+}
+
+//export exportuintptr
+func exportuintptr() uintptr {
+       return (uintptr)(0)
+}
+
+//export exportint8
+func exportint8() int8 {
+       return 0
+}
+
+//export exportuint8
+func exportuint8() uint8 {
+       return 0
+}
+
+//export exportint16
+func exportint16() int16 {
+       return 0
+}
+
+//export exportuint16
+func exportuint16() uint16 {
+       return 0
+}
+
+//export exportint32
+func exportint32() int32 {
+       return 0
+}
+
+//export exportuint32
+func exportuint32() uint32 {
+       return 0
+}
+
+//export exportint64
+func exportint64() int64 {
+       return 0
+}
+
+//export exportuint64
+func exportuint64() uint64 {
+       return 0
+}
+
+//export exportfloat32
+func exportfloat32() float32 {
+       return 0
+}
+
+//export exportfloat64
+func exportfloat64() float64 {
+       return 0
+}
+
+//export exportcomplex64
+func exportcomplex64() complex64 {
+       return 0
+}
+
+//export exportcomplex128
+func exportcomplex128() complex128 {
+       return 0
+}
diff --git a/libgo/misc/cgo/test/issue3250.go b/libgo/misc/cgo/test/issue3250.go
new file mode 100644 (file)
index 0000000..f85c16b
--- /dev/null
@@ -0,0 +1,95 @@
+// Copyright 2013 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 !windows
+
+package cgotest
+
+/*
+#include <signal.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+static void *thread(void *p) {
+       const int M = 100;
+       int i;
+       (void)p;
+       for (i = 0; i < M; i++) {
+               pthread_kill(pthread_self(), SIGCHLD);
+               usleep(rand() % 20 + 5);
+       }
+       return NULL;
+}
+void testSendSIG() {
+       const int N = 20;
+       int i;
+       pthread_t tid[N];
+       for (i = 0; i < N; i++) {
+               usleep(rand() % 200 + 100);
+               pthread_create(&tid[i], 0, thread, NULL);
+       }
+       for (i = 0; i < N; i++)
+               pthread_join(tid[i], 0);
+}
+*/
+import "C"
+
+import (
+       "os"
+       "os/signal"
+       "syscall"
+       "testing"
+       "time"
+)
+
+func test3250(t *testing.T) {
+       t.Skip("skipped, see golang.org/issue/5885")
+       const (
+               thres = 1
+               sig   = syscall.SIGCHLD
+       )
+       type result struct {
+               n   int
+               sig os.Signal
+       }
+       var (
+               sigCh     = make(chan os.Signal, 10)
+               waitStart = make(chan struct{})
+               waitDone  = make(chan result)
+       )
+
+       signal.Notify(sigCh, sig)
+
+       go func() {
+               n := 0
+               alarm := time.After(time.Second * 3)
+               for {
+                       select {
+                       case <-waitStart:
+                               waitStart = nil
+                       case v := <-sigCh:
+                               n++
+                               if v != sig || n > thres {
+                                       waitDone <- result{n, v}
+                                       return
+                               }
+                       case <-alarm:
+                               waitDone <- result{n, sig}
+                               return
+                       }
+               }
+       }()
+
+       waitStart <- struct{}{}
+       C.testSendSIG()
+       r := <-waitDone
+       if r.sig != sig {
+               t.Fatalf("received signal %v, but want %v", r.sig, sig)
+       }
+       t.Logf("got %d signals\n", r.n)
+       if r.n <= thres {
+               t.Fatalf("expected more than %d", thres)
+       }
+}
diff --git a/libgo/misc/cgo/test/issue3250w.go b/libgo/misc/cgo/test/issue3250w.go
new file mode 100644 (file)
index 0000000..c2193aa
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2013 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 windows
+
+package cgotest
+
+import "testing"
+
+func test3250(t *testing.T) {}
diff --git a/libgo/misc/cgo/test/issue3261.go b/libgo/misc/cgo/test/issue3261.go
new file mode 100644 (file)
index 0000000..7137569
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2012 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.
+
+package cgotest
+
+/*
+// libgcc on ARM might be compiled as thumb code, but our 5l
+// can't handle that, so we have to disable this test on arm.
+#ifdef __ARMEL__
+#include <stdio.h>
+int vabs(int x) {
+       puts("testLibgcc is disabled on ARM because 5l cannot handle thumb library.");
+       return (x < 0) ? -x : x;
+}
+#elif defined(__arm64__) && defined(__clang__)
+#include <stdio.h>
+int vabs(int x) {
+       puts("testLibgcc is disabled on ARM64 with clang due to lack of libgcc.");
+       return (x < 0) ? -x : x;
+}
+#else
+int __absvsi2(int); // dummy prototype for libgcc function
+// we shouldn't name the function abs, as gcc might use
+// the builtin one.
+int vabs(int x) { return __absvsi2(x); }
+#endif
+*/
+import "C"
+
+import "testing"
+
+func testLibgcc(t *testing.T) {
+       var table = []struct {
+               in, out C.int
+       }{
+               {0, 0},
+               {1, 1},
+               {-42, 42},
+               {1000300, 1000300},
+               {1 - 1<<31, 1<<31 - 1},
+       }
+       for _, v := range table {
+               if o := C.vabs(v.in); o != v.out {
+                       t.Fatalf("abs(%d) got %d, should be %d", v.in, o, v.out)
+                       return
+               }
+       }
+}
diff --git a/libgo/misc/cgo/test/issue3729.go b/libgo/misc/cgo/test/issue3729.go
new file mode 100644 (file)
index 0000000..947b90a
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2012 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.
+
+// Issue 3729: cmd/cgo: access errno from void C function
+// void f(void) returns [0]byte, error in Go world.
+
+// +build !windows
+
+package cgotest
+
+/*
+#include <errno.h>
+
+void g(void) {
+       errno = E2BIG;
+}
+
+// try to pass some non-trivial arguments to function g2
+const char _expA = 0x42;
+const float _expB = 3.14159;
+const short _expC = 0x55aa;
+const int _expD = 0xdeadbeef;
+void g2(int x, char a, float b, short c, int d) {
+       if (a == _expA && b == _expB && c == _expC && d == _expD)
+               errno = x;
+       else
+               errno = -1;
+}
+*/
+import "C"
+
+import (
+       "syscall"
+       "testing"
+)
+
+func test3729(t *testing.T) {
+       _, e := C.g()
+       if e != syscall.E2BIG {
+               t.Errorf("got %q, expect %q", e, syscall.E2BIG)
+       }
+       _, e = C.g2(C.EINVAL, C._expA, C._expB, C._expC, C._expD)
+       if e != syscall.EINVAL {
+               t.Errorf("got %q, expect %q", e, syscall.EINVAL)
+       }
+}
diff --git a/libgo/misc/cgo/test/issue3729w.go b/libgo/misc/cgo/test/issue3729w.go
new file mode 100644 (file)
index 0000000..69296b5
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2012 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.
+
+// Issue 3729: cmd/cgo: access errno from void C function
+// void f(void) returns [0]byte, error in Go world.
+
+// +build windows
+
+package cgotest
+
+import "testing"
+
+func test3729(t *testing.T) {
+       t.Log("skip errno test on Windows")
+}
diff --git a/libgo/misc/cgo/test/issue3741.go b/libgo/misc/cgo/test/issue3741.go
new file mode 100644 (file)
index 0000000..314038c
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2012 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.
+
+package cgotest
+
+import "C"
+
+//export exportSliceIn
+func exportSliceIn(s []byte) bool {
+       return len(s) == cap(s)
+}
+
+//export exportSliceOut
+func exportSliceOut() []byte {
+       return []byte{1}
+}
+
+//export exportSliceInOut
+func exportSliceInOut(s []byte) []byte {
+       return s
+}
diff --git a/libgo/misc/cgo/test/issue3775.go b/libgo/misc/cgo/test/issue3775.go
new file mode 100644 (file)
index 0000000..5aca760
--- /dev/null
@@ -0,0 +1,39 @@
+// +build !android
+
+package cgotest
+
+/*
+void lockOSThreadCallback(void);
+inline static void lockOSThreadC(void)
+{
+        lockOSThreadCallback();
+}
+int usleep(unsigned usec);
+*/
+import "C"
+
+import (
+       "runtime"
+       "testing"
+)
+
+func init() {
+       // Same as test3775 but run during init so that
+       // there are two levels of internal runtime lock
+       // (1 for init, 1 for cgo).
+       // This would have been broken by CL 11663043.
+       C.lockOSThreadC()
+}
+
+func test3775(t *testing.T) {
+       // Used to panic because of the UnlockOSThread below.
+       C.lockOSThreadC()
+}
+
+//export lockOSThreadCallback
+func lockOSThreadCallback() {
+       runtime.LockOSThread()
+       runtime.UnlockOSThread()
+       go C.usleep(10000)
+       runtime.Gosched()
+}
diff --git a/libgo/misc/cgo/test/issue3945.go b/libgo/misc/cgo/test/issue3945.go
new file mode 100644 (file)
index 0000000..2f9fe23
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2012 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.
+
+package cgotest
+
+// Test that cgo reserves enough stack space during cgo call.
+// See https://golang.org/issue/3945 for details.
+
+// #include <stdio.h>
+//
+// void say() {
+//    printf("%s from C\n", "hello");
+// }
+//
+import "C"
+
+import "testing"
+
+func testPrintf(t *testing.T) {
+       C.say()
+}
diff --git a/libgo/misc/cgo/test/issue4029.c b/libgo/misc/cgo/test/issue4029.c
new file mode 100644 (file)
index 0000000..eab3683
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2015 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 !windows
+
+void call4029(void *arg) {
+       void (*fn)(void) = arg;
+       fn();
+}
diff --git a/libgo/misc/cgo/test/issue4029.go b/libgo/misc/cgo/test/issue4029.go
new file mode 100644 (file)
index 0000000..5789b99
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright 2012 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 !windows
+
+package cgotest
+
+/*
+#include <dlfcn.h>
+#cgo linux LDFLAGS: -ldl
+
+extern void call4029(void *arg);
+*/
+import "C"
+
+import (
+       "testing"
+)
+
+var callbacks int
+
+//export IMPIsOpaque
+func IMPIsOpaque() {
+       callbacks++
+}
+
+//export IMPInitWithFrame
+func IMPInitWithFrame() {
+       callbacks++
+}
+
+//export IMPDrawRect
+func IMPDrawRect() {
+       callbacks++
+}
+
+//export IMPWindowResize
+func IMPWindowResize() {
+       callbacks++
+}
+
+func test4029(t *testing.T) {
+       loadThySelf(t, "IMPWindowResize")
+       loadThySelf(t, "IMPDrawRect")
+       loadThySelf(t, "IMPInitWithFrame")
+       loadThySelf(t, "IMPIsOpaque")
+       if callbacks != 4 {
+               t.Errorf("got %d callbacks, expected 4", callbacks)
+       }
+}
+
+func loadThySelf(t *testing.T, symbol string) {
+       this_process := C.dlopen(nil, C.RTLD_NOW)
+       if this_process == nil {
+               t.Error("dlopen:", C.GoString(C.dlerror()))
+               return
+       }
+       defer C.dlclose(this_process)
+
+       symbol_address := C.dlsym(this_process, C.CString(symbol))
+       if symbol_address == nil {
+               t.Error("dlsym:", C.GoString(C.dlerror()))
+               return
+       }
+       t.Log(symbol, symbol_address)
+       C.call4029(symbol_address)
+}
diff --git a/libgo/misc/cgo/test/issue4029w.go b/libgo/misc/cgo/test/issue4029w.go
new file mode 100644 (file)
index 0000000..18c7201
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2012 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 windows
+
+package cgotest
+
+import "testing"
+
+func test4029(t *testing.T) {
+}
diff --git a/libgo/misc/cgo/test/issue4054a.go b/libgo/misc/cgo/test/issue4054a.go
new file mode 100644 (file)
index 0000000..2abdac5
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2012 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.
+
+package cgotest
+
+/*
+typedef enum {
+       A = 0,
+       B,
+       C,
+       D,
+       E,
+       F,
+       G,
+       H,
+       I,
+       J,
+} issue4054a;
+*/
+import "C"
+
+var issue4054a = []int{C.A, C.B, C.C, C.D, C.E, C.F, C.G, C.H, C.I, C.J}
diff --git a/libgo/misc/cgo/test/issue4054b.go b/libgo/misc/cgo/test/issue4054b.go
new file mode 100644 (file)
index 0000000..048964c
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2012 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.
+
+package cgotest
+
+/*
+typedef enum {
+       A = 0,
+       B,
+       C,
+       D,
+       E,
+       F,
+       G,
+       H,
+       I,
+       J,
+} issue4054b;
+*/
+import "C"
+
+var issue4054b = []int{C.A, C.B, C.C, C.D, C.E, C.F, C.G, C.H, C.I, C.J}
diff --git a/libgo/misc/cgo/test/issue4273.c b/libgo/misc/cgo/test/issue4273.c
new file mode 100644 (file)
index 0000000..cac9876
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2012 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.
+
+#ifdef __ELF__
+__attribute__((weak))
+__attribute__((visibility("hidden")))
+void _compilerrt_abort_impl(const char *file, int line, const char *func) {
+}
+#endif
diff --git a/libgo/misc/cgo/test/issue4273b.c b/libgo/misc/cgo/test/issue4273b.c
new file mode 100644 (file)
index 0000000..71e3f0d
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2012 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.
+
+#ifdef __ELF__
+extern void _compilerrt_abort_impl(const char *file, int line, const char *func);
+
+void __my_abort(const char *file, int line, const char *func) {
+       _compilerrt_abort_impl(file, line, func);
+}
+#endif
diff --git a/libgo/misc/cgo/test/issue4339.c b/libgo/misc/cgo/test/issue4339.c
new file mode 100644 (file)
index 0000000..15d0004
--- /dev/null
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include "issue4339.h"
+
+static void
+impl(void)
+{
+       //printf("impl\n");
+}
+
+Issue4339 exported4339 = {"bar", impl};
+
+void
+handle4339(Issue4339 *x)
+{
+       //printf("handle\n");
+       x->bar();
+       //printf("done\n");
+}
diff --git a/libgo/misc/cgo/test/issue4339.go b/libgo/misc/cgo/test/issue4339.go
new file mode 100644 (file)
index 0000000..4fa4b2b
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2013 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.
+
+package cgotest
+
+/*
+#include "issue4339.h"
+*/
+import "C"
+
+import "testing"
+
+func test4339(t *testing.T) {
+       C.handle4339(&C.exported4339)
+}
diff --git a/libgo/misc/cgo/test/issue4339.h b/libgo/misc/cgo/test/issue4339.h
new file mode 100644 (file)
index 0000000..20f6ceb
--- /dev/null
@@ -0,0 +1,9 @@
+typedef struct Issue4339 Issue4339;
+
+struct Issue4339 {
+       char *name;
+       void (*bar)(void);
+};
+
+extern Issue4339 exported4339;
+void   handle4339(Issue4339*);
diff --git a/libgo/misc/cgo/test/issue4417.go b/libgo/misc/cgo/test/issue4417.go
new file mode 100644 (file)
index 0000000..9b18287
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright 2012 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.
+
+// Issue 4417: cmd/cgo: bool alignment/padding issue.
+// bool alignment is wrong and causing wrong arguments when calling functions.
+//
+
+package cgotest
+
+/*
+#include <stdbool.h>
+
+static int c_bool(bool a, bool b, int c, bool d, bool e)  {
+   return c;
+}
+*/
+import "C"
+import "testing"
+
+func testBoolAlign(t *testing.T) {
+       b := C.c_bool(true, true, 10, true, false)
+       if b != 10 {
+               t.Fatalf("found %d expected 10\n", b)
+       }
+       b = C.c_bool(true, true, 5, true, true)
+       if b != 5 {
+               t.Fatalf("found %d expected 5\n", b)
+       }
+       b = C.c_bool(true, true, 3, true, false)
+       if b != 3 {
+               t.Fatalf("found %d expected 3\n", b)
+       }
+       b = C.c_bool(false, false, 1, true, false)
+       if b != 1 {
+               t.Fatalf("found %d expected 1\n", b)
+       }
+       b = C.c_bool(false, true, 200, true, false)
+       if b != 200 {
+               t.Fatalf("found %d expected 200\n", b)
+       }
+}
diff --git a/libgo/misc/cgo/test/issue4857.go b/libgo/misc/cgo/test/issue4857.go
new file mode 100644 (file)
index 0000000..b18979b
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2013 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.
+
+package cgotest
+
+/*
+#cgo CFLAGS: -Werror
+const struct { int a; } *issue4857() { return (void *)0; }
+*/
+import "C"
+
+func test4857() {
+       _ = C.issue4857()
+}
diff --git a/libgo/misc/cgo/test/issue5227.go b/libgo/misc/cgo/test/issue5227.go
new file mode 100644 (file)
index 0000000..53c3bf1
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2013 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.
+
+// Issue 5227: linker incorrectly treats common symbols and
+// leaves them undefined.
+
+package cgotest
+
+/*
+typedef struct {
+        int Count;
+} Fontinfo;
+
+Fontinfo SansTypeface;
+
+extern void init();
+
+Fontinfo loadfont() {
+        Fontinfo f = {0};
+        return f;
+}
+
+void init() {
+        SansTypeface = loadfont();
+}
+*/
+import "C"
+
+import "testing"
+
+func test5227(t *testing.T) {
+       C.init()
+}
+
+func selectfont() C.Fontinfo {
+       return C.SansTypeface
+}
diff --git a/libgo/misc/cgo/test/issue5242.go b/libgo/misc/cgo/test/issue5242.go
new file mode 100644 (file)
index 0000000..c81cd40
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2014 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.
+
+// Issue 5242.  Cgo incorrectly computed the alignment of structs
+// with no Go accessible fields as 0, and then panicked on
+// modulo-by-zero computations.
+
+package cgotest
+
+/*
+typedef struct {
+} foo;
+
+typedef struct {
+       int x : 1;
+} bar;
+
+int issue5242(foo f, bar b) {
+       return 5242;
+}
+*/
+import "C"
+
+import "testing"
+
+func test5242(t *testing.T) {
+       if got := C.issue5242(C.foo{}, C.bar{}); got != 5242 {
+               t.Errorf("got %v", got)
+       }
+}
diff --git a/libgo/misc/cgo/test/issue5337.go b/libgo/misc/cgo/test/issue5337.go
new file mode 100644 (file)
index 0000000..9041d95
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2013 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 !windows
+
+package cgotest
+
+/*
+#include <signal.h>
+#include <pthread.h>
+
+static void *thread1(void *p) {
+       (void)p;
+       pthread_kill(pthread_self(), SIGPROF);
+       return NULL;
+}
+void test5337() {
+       pthread_t tid;
+       pthread_create(&tid, 0, thread1, NULL);
+       pthread_join(tid, 0);
+}
+*/
+import "C"
+
+import "testing"
+
+// Verify that we can withstand SIGPROF received on foreign threads
+func test5337(t *testing.T) {
+       C.test5337()
+}
diff --git a/libgo/misc/cgo/test/issue5337w.go b/libgo/misc/cgo/test/issue5337w.go
new file mode 100644 (file)
index 0000000..7b46757
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2013 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 windows
+
+package cgotest
+
+import "testing"
+
+func test5337(t *testing.T) {}
diff --git a/libgo/misc/cgo/test/issue5548.go b/libgo/misc/cgo/test/issue5548.go
new file mode 100644 (file)
index 0000000..0710da7
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2013 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.
+
+package cgotest
+
+import "testing"
+
+/*
+extern int issue5548_in_c(void);
+*/
+import "C"
+
+//export issue5548FromC
+func issue5548FromC(s string, i int) int {
+       if len(s) == 4 && s == "test" && i == 42 {
+               return 12345
+       }
+       println("got", len(s), i)
+       return 9876
+}
+
+func test5548(t *testing.T) {
+       if x := C.issue5548_in_c(); x != 12345 {
+               t.Errorf("issue5548_in_c = %d, want %d", x, 12345)
+       }
+}
diff --git a/libgo/misc/cgo/test/issue5548_c.c b/libgo/misc/cgo/test/issue5548_c.c
new file mode 100644 (file)
index 0000000..8411526
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2013 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.
+
+#include "_cgo_export.h"
+
+static void clobber_stack() {
+       volatile char a[1024];
+       int i;
+       for(i = 0; i < sizeof a; i++)
+               a[i] = 0xff;
+}
+
+static int call_go() {
+       GoString s;
+       s.p = "test";
+       s.n = 4;
+       return issue5548FromC(s, 42);
+}
+
+int issue5548_in_c() {
+       clobber_stack();
+       return call_go();
+}
diff --git a/libgo/misc/cgo/test/issue5603.go b/libgo/misc/cgo/test/issue5603.go
new file mode 100644 (file)
index 0000000..ab84339
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2013 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.
+
+package cgotest
+
+/*
+const long long issue5603exp = 0x12345678;
+long long issue5603foo0() { return issue5603exp; }
+long long issue5603foo1(void *p) { return issue5603exp; }
+long long issue5603foo2(void *p, void *q) { return issue5603exp; }
+long long issue5603foo3(void *p, void *q, void *r) { return issue5603exp; }
+long long issue5603foo4(void *p, void *q, void *r, void *s) { return issue5603exp; }
+*/
+import "C"
+
+import "testing"
+
+func test5603(t *testing.T) {
+       var x [5]int64
+       exp := int64(C.issue5603exp)
+       x[0] = int64(C.issue5603foo0())
+       x[1] = int64(C.issue5603foo1(nil))
+       x[2] = int64(C.issue5603foo2(nil, nil))
+       x[3] = int64(C.issue5603foo3(nil, nil, nil))
+       x[4] = int64(C.issue5603foo4(nil, nil, nil, nil))
+       for i, v := range x {
+               if v != exp {
+                       t.Errorf("issue5603foo%d() returns %v, expected %v", i, v, exp)
+               }
+       }
+}
diff --git a/libgo/misc/cgo/test/issue5740.go b/libgo/misc/cgo/test/issue5740.go
new file mode 100644 (file)
index 0000000..059e316
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2013 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.
+
+package cgotest
+
+// int test5740a(void), test5740b(void);
+import "C"
+import "testing"
+
+func test5740(t *testing.T) {
+       if v := C.test5740a() + C.test5740b(); v != 5 {
+               t.Errorf("expected 5, got %v", v)
+       }
+}
diff --git a/libgo/misc/cgo/test/issue5740a.c b/libgo/misc/cgo/test/issue5740a.c
new file mode 100644 (file)
index 0000000..a6a7d0c
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2013 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.
+
+static int volatile val = 2;
+
+int test5740a() {
+       return val;
+}
diff --git a/libgo/misc/cgo/test/issue5740b.c b/libgo/misc/cgo/test/issue5740b.c
new file mode 100644 (file)
index 0000000..c2ff5fb
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2013 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.
+
+static int volatile val = 3;
+
+int test5740b() {
+       return val;
+}
diff --git a/libgo/misc/cgo/test/issue5986.go b/libgo/misc/cgo/test/issue5986.go
new file mode 100644 (file)
index 0000000..9be1614
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2013 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.
+
+package cgotest
+
+/*
+#cgo LDFLAGS: -lm
+#include <stdio.h>
+#include <math.h>
+
+static void output5986()
+{
+    int current_row = 0, row_count = 0;
+    double sum_squares = 0;
+    double d;
+    do {
+        if (current_row == 10) {
+            current_row = 0;
+        }
+        ++row_count;
+    }
+    while (current_row++ != 1);
+    d =  sqrt(sum_squares / row_count);
+    printf("sqrt is: %g\n", d);
+}
+*/
+import "C"
+import "testing"
+
+func test5986(t *testing.T) {
+       C.output5986()
+}
diff --git a/libgo/misc/cgo/test/issue6128.go b/libgo/misc/cgo/test/issue6128.go
new file mode 100644 (file)
index 0000000..9832d79
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2013 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.
+
+package cgotest
+
+// Test handling of #defined names in clang.
+// golang.org/issue/6128.
+
+/*
+// NOTE: Must use hex, or else a shortcut for decimals
+// in cgo avoids trying to pass this to clang.
+#define X 0x1
+*/
+import "C"
+
+func test6128() {
+       // nothing to run, just make sure this compiles.
+       _ = C.X
+}
diff --git a/libgo/misc/cgo/test/issue6390.go b/libgo/misc/cgo/test/issue6390.go
new file mode 100644 (file)
index 0000000..5642899
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2013 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.
+
+package cgotest
+
+// #include <stdlib.h>
+import "C"
+
+import "testing"
+
+func test6390(t *testing.T) {
+       p1 := C.malloc(1024)
+       if p1 == nil {
+               t.Fatalf("C.malloc(1024) returned nil")
+       }
+       p2 := C.malloc(0)
+       if p2 == nil {
+               t.Fatalf("C.malloc(0) returned nil")
+       }
+       C.free(p1)
+       C.free(p2)
+}
diff --git a/libgo/misc/cgo/test/issue6472.go b/libgo/misc/cgo/test/issue6472.go
new file mode 100644 (file)
index 0000000..d416a05
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2013 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.
+
+package cgotest
+
+/*
+typedef struct
+{
+        struct
+        {
+            int x;
+        } y[16];
+} z;
+*/
+import "C"
+
+func test6472() {
+       // nothing to run, just make sure this compiles
+       s := new(C.z)
+       println(s.y[0].x)
+}
diff --git a/libgo/misc/cgo/test/issue6506.go b/libgo/misc/cgo/test/issue6506.go
new file mode 100644 (file)
index 0000000..c54b54b
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2013 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.
+
+package cgotest
+
+// Test handling of size_t in the face of incorrect clang debug information.
+// golang.org/issue/6506.
+
+/*
+#include <stdlib.h>
+#include <string.h>
+*/
+import "C"
+
+func test6506() {
+       // nothing to run, just make sure this compiles
+       var x C.size_t
+
+       C.calloc(x, x)
+       C.malloc(x)
+       C.realloc(nil, x)
+       C.memcpy(nil, nil, x)
+       C.memcmp(nil, nil, x)
+       C.memmove(nil, nil, x)
+       C.strncpy(nil, nil, x)
+       C.strncmp(nil, nil, x)
+       C.strncat(nil, nil, x)
+       x = C.strxfrm(nil, nil, x)
+       C.memchr(nil, 0, x)
+       x = C.strcspn(nil, nil)
+       x = C.strspn(nil, nil)
+       C.memset(nil, 0, x)
+       x = C.strlen(nil)
+       _ = x
+}
diff --git a/libgo/misc/cgo/test/issue6612.go b/libgo/misc/cgo/test/issue6612.go
new file mode 100644 (file)
index 0000000..c337f91
--- /dev/null
@@ -0,0 +1,93 @@
+// Copyright 2013 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.
+
+// golang.org/issue/6612
+// Test new scheme for deciding whether C.name is an expression, type, constant.
+// Clang silences some warnings when the name is a #defined macro, so test those too
+// (even though we now use errors exclusively, not warnings).
+
+package cgotest
+
+/*
+void myfunc(void) {}
+int myvar = 5;
+const char *mytext = "abcdef";
+typedef int mytype;
+enum {
+       myenum = 1234,
+};
+
+#define myfunc_def myfunc
+#define myvar_def myvar
+#define mytext_def mytext
+#define mytype_def mytype
+#define myenum_def myenum
+#define myint_def 12345
+#define myfloat_def 1.5
+#define mystring_def "hello"
+*/
+import "C"
+
+import "testing"
+
+func testNaming(t *testing.T) {
+       C.myfunc()
+       C.myfunc_def()
+       if v := C.myvar; v != 5 {
+               t.Errorf("C.myvar = %d, want 5", v)
+       }
+       if v := C.myvar_def; v != 5 {
+               t.Errorf("C.myvar_def = %d, want 5", v)
+       }
+       if s := C.GoString(C.mytext); s != "abcdef" {
+               t.Errorf("C.mytext = %q, want %q", s, "abcdef")
+       }
+       if s := C.GoString(C.mytext_def); s != "abcdef" {
+               t.Errorf("C.mytext_def = %q, want %q", s, "abcdef")
+       }
+       if c := C.myenum; c != 1234 {
+               t.Errorf("C.myenum = %v, want 1234", c)
+       }
+       if c := C.myenum_def; c != 1234 {
+               t.Errorf("C.myenum_def = %v, want 1234", c)
+       }
+       {
+               const c = C.myenum
+               if c != 1234 {
+                       t.Errorf("C.myenum as const = %v, want 1234", c)
+               }
+       }
+       {
+               const c = C.myenum_def
+               if c != 1234 {
+                       t.Errorf("C.myenum as const = %v, want 1234", c)
+               }
+       }
+       if c := C.myint_def; c != 12345 {
+               t.Errorf("C.myint_def = %v, want 12345", c)
+       }
+       {
+               const c = C.myint_def
+               if c != 12345 {
+                       t.Errorf("C.myint as const = %v, want 12345", c)
+               }
+       }
+
+       // This would be nice, but it has never worked.
+       /*
+               if c := C.myfloat_def; c != 1.5 {
+                       t.Errorf("C.myint_def = %v, want 1.5", c)
+               }
+               {
+                       const c = C.myfloat_def
+                       if c != 1.5 {
+                       t.Errorf("C.myint as const = %v, want 1.5", c)
+                       }
+               }
+       */
+
+       if s := C.mystring_def; s != "hello" {
+               t.Errorf("C.mystring_def = %q, want %q", s, "hello")
+       }
+}
diff --git a/libgo/misc/cgo/test/issue6833.go b/libgo/misc/cgo/test/issue6833.go
new file mode 100644 (file)
index 0000000..de60dbf
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2013 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.
+
+package cgotest
+
+/*
+extern unsigned long long issue6833Func(unsigned int, unsigned long long);
+*/
+import "C"
+
+import "testing"
+
+//export GoIssue6833Func
+func GoIssue6833Func(aui uint, aui64 uint64) uint64 {
+       return aui64 + uint64(aui)
+}
+
+func test6833(t *testing.T) {
+       ui := 7
+       ull := uint64(0x4000300020001000)
+       v := uint64(C.issue6833Func(C.uint(ui), C.ulonglong(ull)))
+       exp := uint64(ui) + ull
+       if v != exp {
+               t.Errorf("issue6833Func() returns %x, expected %x", v, exp)
+       }
+}
diff --git a/libgo/misc/cgo/test/issue6833_c.c b/libgo/misc/cgo/test/issue6833_c.c
new file mode 100644 (file)
index 0000000..c94c2c6
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2013 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.
+
+#include "_cgo_export.h"
+unsigned long long
+issue6833Func(unsigned int aui, unsigned long long aull) {
+       return GoIssue6833Func(aui, aull);
+}
diff --git a/libgo/misc/cgo/test/issue6997_linux.c b/libgo/misc/cgo/test/issue6997_linux.c
new file mode 100644 (file)
index 0000000..de803d2
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2014 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 !android
+
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static pthread_t thread;
+
+static void* threadfunc(void* dummy) {
+       while(1) {
+               sleep(1);
+       }
+}
+
+int StartThread() {
+       return pthread_create(&thread, NULL, &threadfunc, NULL);
+}
+
+int CancelThread() {
+       void *r;
+       pthread_cancel(thread);
+       pthread_join(thread, &r);
+       return (r == PTHREAD_CANCELED);
+}
diff --git a/libgo/misc/cgo/test/issue6997_linux.go b/libgo/misc/cgo/test/issue6997_linux.go
new file mode 100644 (file)
index 0000000..0c98ea0
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright 2014 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 !android
+
+// Test that pthread_cancel works as expected
+// (NPTL uses SIGRTMIN to implement thread cancelation)
+// See https://golang.org/issue/6997
+package cgotest
+
+/*
+#cgo CFLAGS: -pthread
+#cgo LDFLAGS: -pthread
+extern int StartThread();
+extern int CancelThread();
+*/
+import "C"
+
+import "testing"
+import "time"
+
+func test6997(t *testing.T) {
+       r := C.StartThread()
+       if r != 0 {
+               t.Error("pthread_create failed")
+       }
+       c := make(chan C.int)
+       go func() {
+               time.Sleep(500 * time.Millisecond)
+               c <- C.CancelThread()
+       }()
+
+       select {
+       case r = <-c:
+               if r == 0 {
+                       t.Error("pthread finished but wasn't canceled??")
+               }
+       case <-time.After(30 * time.Second):
+               t.Error("hung in pthread_cancel/pthread_join")
+       }
+}
diff --git a/libgo/misc/cgo/test/issue7234_test.go b/libgo/misc/cgo/test/issue7234_test.go
new file mode 100644 (file)
index 0000000..c191a1a
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2014 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.
+
+package cgotest
+
+import "testing"
+
+// This test actually doesn't have anything to do with cgo.  It is a
+// test of https://golang.org/issue/7234, a compiler/linker bug in
+// handling string constants when using -linkmode=external.  The test
+// is in this directory because we routinely test -linkmode=external
+// here.
+
+var v7234 = [...]string{"runtime/cgo"}
+
+func Test7234(t *testing.T) {
+       if v7234[0] != "runtime/cgo" {
+               t.Errorf("bad string constant %q", v7234[0])
+       }
+}
diff --git a/libgo/misc/cgo/test/issue7560.go b/libgo/misc/cgo/test/issue7560.go
new file mode 100644 (file)
index 0000000..f36d8a1
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2014 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.
+
+package cgotest
+
+/*
+#include <stdint.h>
+
+typedef struct {
+       char x;
+       long y;
+} __attribute__((__packed__)) misaligned;
+
+int
+offset7560(void)
+{
+       return (uintptr_t)&((misaligned*)0)->y;
+}
+*/
+import "C"
+
+import (
+       "reflect"
+       "testing"
+)
+
+func test7560(t *testing.T) {
+       // some mingw don't implement __packed__ correctly.
+       if C.offset7560() != 1 {
+               t.Skip("C compiler did not pack struct")
+       }
+
+       // C.misaligned should have x but then a padding field to get to the end of the struct.
+       // There should not be a field named 'y'.
+       var v C.misaligned
+       rt := reflect.TypeOf(&v).Elem()
+       if rt.NumField() != 2 || rt.Field(0).Name != "x" || rt.Field(1).Name != "_" {
+               t.Errorf("unexpected fields in C.misaligned:\n")
+               for i := 0; i < rt.NumField(); i++ {
+                       t.Logf("%+v\n", rt.Field(i))
+               }
+       }
+}
diff --git a/libgo/misc/cgo/test/issue7665.go b/libgo/misc/cgo/test/issue7665.go
new file mode 100644 (file)
index 0000000..ce03458
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2013 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.
+
+package cgotest
+
+import (
+       "testing"
+       "unsafe"
+)
+
+// extern void f7665(void);
+import "C"
+
+//export f7665
+func f7665() {}
+
+var bad7665 unsafe.Pointer = C.f7665
+var good7665 uintptr = uintptr(C.f7665)
+
+func test7665(t *testing.T) {
+       if bad7665 == nil || uintptr(bad7665) != good7665 {
+               t.Errorf("ptrs = %p, %#x, want same non-nil pointer", bad7665, good7665)
+       }
+}
diff --git a/libgo/misc/cgo/test/issue7786.go b/libgo/misc/cgo/test/issue7786.go
new file mode 100644 (file)
index 0000000..1344e9e
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright 2013 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.
+
+// Issue 7786. No runtime test, just make sure that typedef and struct/union/class are interchangeable at compile time.
+
+package cgotest
+
+// struct test7786;
+// typedef struct test7786 typedef_test7786;
+// void f7786(struct test7786 *ctx) {}
+// void g7786(typedef_test7786 *ctx) {}
+//
+// typedef struct body7786 typedef_body7786;
+// struct body7786 { int x; };
+// void b7786(struct body7786 *ctx) {}
+// void c7786(typedef_body7786 *ctx) {}
+//
+// typedef union union7786 typedef_union7786;
+// void u7786(union union7786 *ctx) {}
+// void v7786(typedef_union7786 *ctx) {}
+import "C"
+
+func f() {
+       var x1 *C.typedef_test7786
+       var x2 *C.struct_test7786
+       x1 = x2
+       x2 = x1
+       C.f7786(x1)
+       C.f7786(x2)
+       C.g7786(x1)
+       C.g7786(x2)
+
+       var b1 *C.typedef_body7786
+       var b2 *C.struct_body7786
+       b1 = b2
+       b2 = b1
+       C.b7786(b1)
+       C.b7786(b2)
+       C.c7786(b1)
+       C.c7786(b2)
+
+       var u1 *C.typedef_union7786
+       var u2 *C.union_union7786
+       u1 = u2
+       u2 = u1
+       C.u7786(u1)
+       C.u7786(u2)
+       C.v7786(u1)
+       C.v7786(u2)
+}
diff --git a/libgo/misc/cgo/test/issue7978.go b/libgo/misc/cgo/test/issue7978.go
new file mode 100644 (file)
index 0000000..7fb62e8
--- /dev/null
@@ -0,0 +1,138 @@
+// Copyright 2014 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.
+
+// Issue 7978.  Stack tracing didn't work during cgo code after calling a Go
+// callback.  Make sure GC works and the stack trace is correct.
+
+package cgotest
+
+/*
+#include <stdint.h>
+
+void issue7978cb(void);
+
+#if defined(__APPLE__) && defined(__arm__)
+// on Darwin/ARM, libSystem doesn't provide implementation of the __sync_fetch_and_add
+// primitive, and although gcc supports it, it doesn't inline its definition.
+// Clang could inline its definition, so we require clang on Darwin/ARM.
+#if defined(__clang__)
+#define HAS_SYNC_FETCH_AND_ADD 1
+#else
+#define HAS_SYNC_FETCH_AND_ADD 0
+#endif
+#else
+#define HAS_SYNC_FETCH_AND_ADD 1
+#endif
+
+// use ugly atomic variable sync since that doesn't require calling back into
+// Go code or OS dependencies
+static void issue7978c(uint32_t *sync) {
+#if HAS_SYNC_FETCH_AND_ADD
+       while(__sync_fetch_and_add(sync, 0) != 0)
+               ;
+       __sync_fetch_and_add(sync, 1);
+       while(__sync_fetch_and_add(sync, 0) != 2)
+               ;
+       issue7978cb();
+       __sync_fetch_and_add(sync, 1);
+       while(__sync_fetch_and_add(sync, 0) != 6)
+               ;
+#endif
+}
+*/
+import "C"
+
+import (
+       "os"
+       "runtime"
+       "strings"
+       "sync/atomic"
+       "testing"
+)
+
+var issue7978sync uint32
+
+func issue7978check(t *testing.T, wantFunc string, badFunc string, depth int) {
+       runtime.GC()
+       buf := make([]byte, 65536)
+       trace := string(buf[:runtime.Stack(buf, true)])
+       for _, goroutine := range strings.Split(trace, "\n\n") {
+               if strings.Contains(goroutine, "test.issue7978go") {
+                       trace := strings.Split(goroutine, "\n")
+                       // look for the expected function in the stack
+                       for i := 0; i < depth; i++ {
+                               if badFunc != "" && strings.Contains(trace[1+2*i], badFunc) {
+                                       t.Errorf("bad stack: found %s in the stack:\n%s", badFunc, goroutine)
+                                       return
+                               }
+                               if strings.Contains(trace[1+2*i], wantFunc) {
+                                       return
+                               }
+                       }
+                       t.Errorf("bad stack: didn't find %s in the stack:\n%s", wantFunc, goroutine)
+                       return
+               }
+       }
+       t.Errorf("bad stack: goroutine not found. Full stack dump:\n%s", trace)
+}
+
+func issue7978wait(store uint32, wait uint32) {
+       if store != 0 {
+               atomic.StoreUint32(&issue7978sync, store)
+       }
+       for atomic.LoadUint32(&issue7978sync) != wait {
+               runtime.Gosched()
+       }
+}
+
+//export issue7978cb
+func issue7978cb() {
+       // Force a stack growth from the callback to put extra
+       // pressure on the runtime. See issue #17785.
+       growStack(64)
+       issue7978wait(3, 4)
+}
+
+func growStack(n int) int {
+       var buf [128]int
+       if n == 0 {
+               return 0
+       }
+       return buf[growStack(n-1)]
+}
+
+func issue7978go() {
+       C.issue7978c((*C.uint32_t)(&issue7978sync))
+       issue7978wait(7, 8)
+}
+
+func test7978(t *testing.T) {
+       if runtime.Compiler == "gccgo" {
+               t.Skip("gccgo can not do stack traces of C code")
+       }
+       if C.HAS_SYNC_FETCH_AND_ADD == 0 {
+               t.Skip("clang required for __sync_fetch_and_add support on darwin/arm")
+       }
+       if runtime.GOOS == "android" || runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
+               t.Skip("GOTRACEBACK is not passed on to the exec wrapper")
+       }
+       if os.Getenv("GOTRACEBACK") != "2" {
+               t.Fatalf("GOTRACEBACK must be 2")
+       }
+       issue7978sync = 0
+       go issue7978go()
+       // test in c code, before callback
+       issue7978wait(0, 1)
+       issue7978check(t, "_Cfunc_issue7978c(", "", 1)
+       // test in go code, during callback
+       issue7978wait(2, 3)
+       issue7978check(t, "test.issue7978cb(", "test.issue7978go", 3)
+       // test in c code, after callback
+       issue7978wait(4, 5)
+       issue7978check(t, "_Cfunc_issue7978c(", "_cgoexpwrap", 1)
+       // test in go code, after return from cgo
+       issue7978wait(6, 7)
+       issue7978check(t, "test.issue7978go(", "", 3)
+       atomic.StoreUint32(&issue7978sync, 8)
+}
diff --git a/libgo/misc/cgo/test/issue8092.go b/libgo/misc/cgo/test/issue8092.go
new file mode 100644 (file)
index 0000000..19123e7
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2014 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.
+
+// Issue 8092. Test that linker defined symbols (e.g., text, data) don't
+// conflict with C symbols.
+
+package cgotest
+
+/*
+char text[] = "text";
+char data[] = "data";
+char *ctext(void) { return text; }
+char *cdata(void) { return data; }
+*/
+import "C"
+
+import "testing"
+
+func test8092(t *testing.T) {
+       tests := []struct {
+               s    string
+               a, b *C.char
+       }{
+               {"text", &C.text[0], C.ctext()},
+               {"data", &C.data[0], C.cdata()},
+       }
+       for _, test := range tests {
+               if test.a != test.b {
+                       t.Errorf("%s: pointer mismatch: %v != %v", test.s, test.a, test.b)
+               }
+               if got := C.GoString(test.a); got != test.s {
+                       t.Errorf("%s: points at %#v, want %#v", test.s, got, test.s)
+               }
+       }
+}
diff --git a/libgo/misc/cgo/test/issue8148.go b/libgo/misc/cgo/test/issue8148.go
new file mode 100644 (file)
index 0000000..f704788
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2014 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.
+
+// Issue 8148.  A typedef of an unnamed struct didn't work when used
+// with an exported Go function.  No runtime test; just make sure it
+// compiles.
+
+package cgotest
+
+/*
+typedef struct { int i; } T;
+
+int issue8148Callback(T*);
+
+static int get() {
+       T t;
+       t.i = 42;
+       return issue8148Callback(&t);
+}
+*/
+import "C"
+
+//export issue8148Callback
+func issue8148Callback(t *C.T) C.int {
+       return t.i
+}
+
+func Issue8148() int {
+       return int(C.get())
+}
diff --git a/libgo/misc/cgo/test/issue8331.h b/libgo/misc/cgo/test/issue8331.h
new file mode 100644 (file)
index 0000000..8065be0
--- /dev/null
@@ -0,0 +1,7 @@
+// Copyright 2014 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.
+
+typedef struct {
+       int i;
+} issue8331;
diff --git a/libgo/misc/cgo/test/issue8331a.go b/libgo/misc/cgo/test/issue8331a.go
new file mode 100644 (file)
index 0000000..92e2579
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2014 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.
+
+// Issue 8331.  A typedef of an unnamed struct is the same struct when
+// #include'd twice.  No runtime test; just make sure it compiles.
+
+package cgotest
+
+// #include "issue8331.h"
+import "C"
+
+func issue8331a() C.issue8331 {
+       return issue8331Var
+}
diff --git a/libgo/misc/cgo/test/issue8331b.go b/libgo/misc/cgo/test/issue8331b.go
new file mode 100644 (file)
index 0000000..5324aa2
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2014 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.
+
+// Issue 8331.  A typedef of an unnamed struct is the same struct when
+// #include'd twice.  No runtime test; just make sure it compiles.
+
+package cgotest
+
+// #include "issue8331.h"
+import "C"
+
+var issue8331Var C.issue8331
diff --git a/libgo/misc/cgo/test/issue8428.go b/libgo/misc/cgo/test/issue8428.go
new file mode 100644 (file)
index 0000000..2e5a555
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright 2014 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.
+
+// This test fails on older versions of OS X because they use older buggy
+// versions of Clang that emit ambiguous DWARF info.  See issue 8611.
+// +build !darwin
+
+package cgotest
+
+// Issue 8428.  Cgo inconsistently translated zero size arrays.
+
+/*
+struct issue8428one {
+       char b;
+       char rest[];
+};
+
+struct issue8428two {
+       void *p;
+       char b;
+       char rest[0];
+       char pad;
+};
+
+struct issue8428three {
+       char w[1][2][3][0];
+       char x[2][3][0][1];
+       char y[3][0][1][2];
+       char z[0][1][2][3];
+};
+*/
+import "C"
+
+import "unsafe"
+
+var _ = C.struct_issue8428one{
+       b: C.char(0),
+       // The trailing rest field is not available in cgo.
+       // See issue 11925.
+       // rest: [0]C.char{},
+}
+
+var _ = C.struct_issue8428two{
+       p:    unsafe.Pointer(nil),
+       b:    C.char(0),
+       rest: [0]C.char{},
+}
+
+var _ = C.struct_issue8428three{
+       w: [1][2][3][0]C.char{},
+       x: [2][3][0][1]C.char{},
+       y: [3][0][1][2]C.char{},
+       z: [0][1][2][3]C.char{},
+}
diff --git a/libgo/misc/cgo/test/issue8441.go b/libgo/misc/cgo/test/issue8441.go
new file mode 100644 (file)
index 0000000..4489ca9
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2014 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.
+
+// Issue 8368 and 8441.  Recursive struct definitions didn't work.
+// No runtime test; just make sure it compiles.
+
+package cgotest
+
+/*
+typedef struct one one;
+typedef struct two two;
+struct one {
+       two *x;
+};
+struct two {
+       one *x;
+};
+*/
+import "C"
+
+func issue8368(one *C.struct_one, two *C.struct_two) {
+}
+
+func issue8441(one *C.one, two *C.two) {
+       issue8441(two.x, one.x)
+}
diff --git a/libgo/misc/cgo/test/issue8517.go b/libgo/misc/cgo/test/issue8517.go
new file mode 100644 (file)
index 0000000..4e431df
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2014 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 !windows
+
+package cgotest
+
+import "testing"
+
+func test8517(t *testing.T) {
+       t.Skip("skipping windows only test")
+}
diff --git a/libgo/misc/cgo/test/issue8517_windows.c b/libgo/misc/cgo/test/issue8517_windows.c
new file mode 100644 (file)
index 0000000..a0b94c1
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2014 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.
+
+#include "windows.h"
+
+extern void testHandleLeaksCallback();
+
+DWORD WINAPI testHandleLeaksFunc(LPVOID lpThreadParameter)
+{
+       int i;
+       for(i = 0; i < 100; i++) {
+               testHandleLeaksCallback();
+       }
+       return 0;
+}
+
+void testHandleLeaks()
+{
+       HANDLE h;
+       h = CreateThread(NULL, 0, &testHandleLeaksFunc, 0, 0, NULL);
+       WaitForSingleObject(h, INFINITE);
+       CloseHandle(h);
+}
diff --git a/libgo/misc/cgo/test/issue8517_windows.go b/libgo/misc/cgo/test/issue8517_windows.go
new file mode 100644 (file)
index 0000000..3782631
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright 2014 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.
+
+package cgotest
+
+//void testHandleLeaks();
+import "C"
+
+import (
+       "syscall"
+       "testing"
+       "unsafe"
+)
+
+var issue8517counter int
+
+var (
+       kernel32              = syscall.MustLoadDLL("kernel32.dll")
+       getProcessHandleCount = kernel32.MustFindProc("GetProcessHandleCount")
+)
+
+func processHandleCount(t *testing.T) int {
+       const current_process = ^uintptr(0)
+       var c uint32
+       r, _, err := getProcessHandleCount.Call(current_process, uintptr(unsafe.Pointer(&c)))
+       if r == 0 {
+               t.Fatal(err)
+       }
+       return int(c)
+}
+
+func test8517(t *testing.T) {
+       c1 := processHandleCount(t)
+       C.testHandleLeaks()
+       c2 := processHandleCount(t)
+       if c1+issue8517counter <= c2 {
+               t.Fatalf("too many handles leaked: issue8517counter=%v c1=%v c2=%v", issue8517counter, c1, c2)
+       }
+}
+
+//export testHandleLeaksCallback
+func testHandleLeaksCallback() {
+       issue8517counter++
+}
diff --git a/libgo/misc/cgo/test/issue8694.go b/libgo/misc/cgo/test/issue8694.go
new file mode 100644 (file)
index 0000000..89be7ea
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2014 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 !android
+
+package cgotest
+
+/*
+#include <complex.h>
+
+complex float complexFloatSquared(complex float a) { return a*a; }
+complex double complexDoubleSquared(complex double a) { return a*a; }
+*/
+import "C"
+
+import (
+       "runtime"
+       "testing"
+)
+
+func test8694(t *testing.T) {
+       if runtime.GOARCH == "arm" {
+               t.Skip("test8694 is disabled on ARM because 5l cannot handle thumb library.")
+       }
+       // Really just testing that this compiles, but check answer anyway.
+       x := C.complexfloat(2 + 3i)
+       x2 := x * x
+       cx2 := C.complexFloatSquared(x)
+       if cx2 != x2 {
+               t.Errorf("C.complexFloatSquared(%v) = %v, want %v", x, cx2, x2)
+       }
+
+       y := C.complexdouble(2 + 3i)
+       y2 := y * y
+       cy2 := C.complexDoubleSquared(y)
+       if cy2 != y2 {
+               t.Errorf("C.complexDoubleSquared(%v) = %v, want %v", y, cy2, y2)
+       }
+}
diff --git a/libgo/misc/cgo/test/issue8756.go b/libgo/misc/cgo/test/issue8756.go
new file mode 100644 (file)
index 0000000..d8ee3b8
--- /dev/null
@@ -0,0 +1,17 @@
+package cgotest
+
+/*
+#cgo LDFLAGS: -lm
+#include <math.h>
+*/
+import "C"
+import (
+       "testing"
+
+       "./issue8756"
+)
+
+func test8756(t *testing.T) {
+       issue8756.Pow()
+       C.pow(1, 2)
+}
diff --git a/libgo/misc/cgo/test/issue8756/issue8756.go b/libgo/misc/cgo/test/issue8756/issue8756.go
new file mode 100644 (file)
index 0000000..5f6b777
--- /dev/null
@@ -0,0 +1,11 @@
+package issue8756
+
+/*
+#cgo LDFLAGS: -lm
+#include <math.h>
+*/
+import "C"
+
+func Pow() {
+       C.pow(1, 2)
+}
diff --git a/libgo/misc/cgo/test/issue8811.c b/libgo/misc/cgo/test/issue8811.c
new file mode 100644 (file)
index 0000000..41b3c7c
--- /dev/null
@@ -0,0 +1,8 @@
+// Copyright 2014 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.
+
+int issue8811Initialized = 0;
+
+void issue8811Init() {
+}
diff --git a/libgo/misc/cgo/test/issue8811.go b/libgo/misc/cgo/test/issue8811.go
new file mode 100644 (file)
index 0000000..f812732
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2014 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.
+
+package cgotest
+
+/*
+extern int issue8811Initialized;
+extern void issue8811Init();
+
+void issue8811Execute() {
+       if(!issue8811Initialized)
+               issue8811Init();
+}
+*/
+import "C"
+
+import "testing"
+
+func test8811(t *testing.T) {
+       C.issue8811Execute()
+}
diff --git a/libgo/misc/cgo/test/issue8828.go b/libgo/misc/cgo/test/issue8828.go
new file mode 100644 (file)
index 0000000..304797c
--- /dev/null
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2014 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.
+
+// Issue 8828: compiling a file with -compiler=gccgo fails if a .c file
+// has the same name as compiled directory.
+
+package cgotest
+
+import "./issue8828"
+
+func p() {
+       issue8828.Bar()
+}
diff --git a/libgo/misc/cgo/test/issue8828/issue8828.c b/libgo/misc/cgo/test/issue8828/issue8828.c
new file mode 100644 (file)
index 0000000..27ec23a
--- /dev/null
@@ -0,0 +1,7 @@
+// Copyright 2014 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.
+
+void foo()
+{
+}
diff --git a/libgo/misc/cgo/test/issue8828/trivial.go b/libgo/misc/cgo/test/issue8828/trivial.go
new file mode 100644 (file)
index 0000000..e7b9a4e
--- /dev/null
@@ -0,0 +1,8 @@
+package issue8828
+
+//void foo();
+import "C"
+
+func Bar() {
+       C.foo()
+}
diff --git a/libgo/misc/cgo/test/issue8945.go b/libgo/misc/cgo/test/issue8945.go
new file mode 100644 (file)
index 0000000..57a5b2d
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2014 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 gccgo
+
+package cgotest
+
+//typedef void (*PFunc)();
+//PFunc success_cb;
+import "C"
+
+//export Test
+func Test() {
+       _ = C.success_cb
+}
diff --git a/libgo/misc/cgo/test/issue9026.go b/libgo/misc/cgo/test/issue9026.go
new file mode 100644 (file)
index 0000000..8848d0e
--- /dev/null
@@ -0,0 +1,9 @@
+package cgotest
+
+import (
+       "testing"
+
+       "./issue9026"
+)
+
+func test9026(t *testing.T) { issue9026.Test(t) }
diff --git a/libgo/misc/cgo/test/issue9026/issue9026.go b/libgo/misc/cgo/test/issue9026/issue9026.go
new file mode 100644 (file)
index 0000000..0af86e6
--- /dev/null
@@ -0,0 +1,36 @@
+package issue9026
+
+// This file appears in its own package since the assertion tests the
+// per-package counter used to create fresh identifiers.
+
+/*
+typedef struct {} git_merge_file_input;
+
+typedef struct {} git_merge_file_options;
+
+void git_merge_file(
+        git_merge_file_input *in,
+        git_merge_file_options *opts) {}
+*/
+import "C"
+import (
+       "fmt"
+       "testing"
+)
+
+func Test(t *testing.T) {
+       var in C.git_merge_file_input
+       var opts *C.git_merge_file_options
+       C.git_merge_file(&in, opts)
+
+       // Test that the generated type names are deterministic.
+       // (Previously this would fail about 10% of the time.)
+       //
+       // Brittle: the assertion may fail spuriously when the algorithm
+       // changes, but should remain stable otherwise.
+       got := fmt.Sprintf("%T %T", in, opts)
+       want := "issue9026._Ctype_struct___0 *issue9026._Ctype_struct___1"
+       if got != want {
+               t.Errorf("Non-deterministic type names: got %s, want %s", got, want)
+       }
+}
diff --git a/libgo/misc/cgo/test/issue9400/asm_386.s b/libgo/misc/cgo/test/issue9400/asm_386.s
new file mode 100644 (file)
index 0000000..7f158b5
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2014 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 !gccgo
+
+#include "textflag.h"
+
+TEXT Â·RewindAndSetgid(SB),NOSPLIT,$0-0
+       MOVL    $·Baton(SB), BX
+       // Rewind stack pointer so anything that happens on the stack
+       // will clobber the test pattern created by the caller
+       ADDL    $(1024 * 8), SP
+
+       // Ask signaller to setgid
+       MOVL    $1, (BX)
+
+       // Wait for setgid completion
+loop:
+       PAUSE
+       MOVL    (BX), AX
+       CMPL    AX, $0
+       JNE     loop
+
+       // Restore stack
+       SUBL    $(1024 * 8), SP
+       RET
diff --git a/libgo/misc/cgo/test/issue9400/asm_amd64x.s b/libgo/misc/cgo/test/issue9400/asm_amd64x.s
new file mode 100644 (file)
index 0000000..48b8619
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2014 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 amd64 amd64p32
+// +build !gccgo
+
+#include "textflag.h"
+
+TEXT Â·RewindAndSetgid(SB),NOSPLIT,$0-0
+       // Rewind stack pointer so anything that happens on the stack
+       // will clobber the test pattern created by the caller
+       ADDQ    $(1024 * 8), SP
+
+       // Ask signaller to setgid
+       MOVL    $1, Â·Baton(SB)
+
+       // Wait for setgid completion
+loop:
+       PAUSE
+       MOVL    Â·Baton(SB), AX
+       CMPL    AX, $0
+       JNE     loop
+
+       // Restore stack
+       SUBQ    $(1024 * 8), SP
+       RET
diff --git a/libgo/misc/cgo/test/issue9400/asm_arm.s b/libgo/misc/cgo/test/issue9400/asm_arm.s
new file mode 100644 (file)
index 0000000..166d53f
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2014 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 !gccgo
+
+#include "textflag.h"
+
+TEXT cas<>(SB),NOSPLIT,$0
+       MOVW    $0xffff0fc0, R15 // R15 is PC
+
+TEXT Â·RewindAndSetgid(SB),NOSPLIT,$-4-0
+       // Save link register
+       MOVW    R14, R4
+
+       // Rewind stack pointer so anything that happens on the stack
+       // will clobber the test pattern created by the caller
+       ADD     $(1024 * 8), R13
+
+       // Ask signaller to setgid
+       MOVW    $·Baton(SB), R2
+storeloop:
+       MOVW    0(R2), R0
+       MOVW    $1, R1
+       BL      cas<>(SB)
+       BCC     storeloop
+
+       // Wait for setgid completion
+loop:
+       MOVW    $0, R0
+       MOVW    $0, R1
+       BL      cas<>(SB)
+       BCC     loop
+
+       // Restore stack
+       SUB     $(1024 * 8), R13
+
+       MOVW    R4, R14
+       RET
diff --git a/libgo/misc/cgo/test/issue9400/asm_arm64.s b/libgo/misc/cgo/test/issue9400/asm_arm64.s
new file mode 100644 (file)
index 0000000..9bb5081
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2014 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 !gccgo
+
+#include "textflag.h"
+
+TEXT Â·RewindAndSetgid(SB),NOSPLIT,$-8-0
+       // Save link register
+       MOVD    R30, R9
+
+       // Rewind stack pointer so anything that happens on the stack
+       // will clobber the test pattern created by the caller
+       ADD     $(1024 * 8), RSP
+
+       // Ask signaller to setgid
+       MOVD    $·Baton(SB), R0
+       MOVD    $1, R1
+storeloop:
+       LDAXRW  (R0), R2
+       STLXRW  R1, (R0), R3
+       CBNZ    R3, storeloop
+
+       // Wait for setgid completion
+       MOVW    $0, R1
+       MOVW    $0, R2
+loop:
+       LDAXRW  (R0), R3
+       CMPW    R1, R3
+       BNE     loop
+       STLXRW  R2, (R0), R3
+       CBNZ    R3, loop
+
+       // Restore stack
+       SUB     $(1024 * 8), RSP
+
+       MOVD    R9, R30
+       RET
diff --git a/libgo/misc/cgo/test/issue9400/asm_mips64x.s b/libgo/misc/cgo/test/issue9400/asm_mips64x.s
new file mode 100644 (file)
index 0000000..63dc906
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2016 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 mips64 mips64le
+// +build !gccgo
+
+#include "textflag.h"
+
+#define SYNC   WORD $0xf
+
+TEXT Â·RewindAndSetgid(SB),NOSPLIT|NOFRAME,$0-0
+       // Rewind stack pointer so anything that happens on the stack
+       // will clobber the test pattern created by the caller
+       ADDV    $(1024*8), R29
+
+       // Ask signaller to setgid
+       MOVW    $1, R1
+       SYNC
+       MOVW    R1, Â·Baton(SB)
+       SYNC
+
+       // Wait for setgid completion
+loop:
+       SYNC
+       MOVW    Â·Baton(SB), R1
+       OR      R2, R2, R2      // hint that we're in a spin loop
+       BNE     R1, loop
+       SYNC
+
+       // Restore stack
+       ADDV    $(-1024*8), R29
+       RET
diff --git a/libgo/misc/cgo/test/issue9400/asm_mipsx.s b/libgo/misc/cgo/test/issue9400/asm_mipsx.s
new file mode 100644 (file)
index 0000000..ddf33e9
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2016 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 mips mipsle
+// +build !gccgo
+
+#include "textflag.h"
+
+TEXT Â·RewindAndSetgid(SB),NOSPLIT,$-4-0
+       // Rewind stack pointer so anything that happens on the stack
+       // will clobber the test pattern created by the caller
+       ADDU    $(1024*8), R29
+
+       // Ask signaller to setgid
+       MOVW    $1, R1
+       SYNC
+       MOVW    R1, Â·Baton(SB)
+       SYNC
+
+       // Wait for setgid completion
+loop:
+       SYNC
+       MOVW    Â·Baton(SB), R1
+       OR      R2, R2, R2      // hint that we're in a spin loop
+       BNE     R1, loop
+       SYNC
+
+       // Restore stack
+       ADDU    $(-1024*8), R29
+       RET
diff --git a/libgo/misc/cgo/test/issue9400/asm_ppc64x.s b/libgo/misc/cgo/test/issue9400/asm_ppc64x.s
new file mode 100644 (file)
index 0000000..c88ec3b
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2014 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 ppc64 ppc64le
+// +build !gccgo
+
+#include "textflag.h"
+
+TEXT Â·RewindAndSetgid(SB),NOSPLIT|NOFRAME,$0-0
+       // Rewind stack pointer so anything that happens on the stack
+       // will clobber the test pattern created by the caller
+       ADD     $(1024 * 8), R1
+
+       // Ask signaller to setgid
+       MOVW    $1, R3
+       SYNC
+       MOVW    R3, Â·Baton(SB)
+
+       // Wait for setgid completion
+loop:
+       SYNC
+       MOVW    Â·Baton(SB), R3
+       CMP     R3, $0
+       // Hint that we're in a spin loop
+       OR      R1, R1, R1
+       BNE     loop
+       ISYNC
+
+       // Restore stack
+       SUB     $(1024 * 8), R1
+       RET
diff --git a/libgo/misc/cgo/test/issue9400/asm_s390x.s b/libgo/misc/cgo/test/issue9400/asm_s390x.s
new file mode 100644 (file)
index 0000000..fc9ad72
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2016 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 !gccgo
+
+#include "textflag.h"
+
+TEXT Â·RewindAndSetgid(SB),NOSPLIT,$0-0
+       // Rewind stack pointer so anything that happens on the stack
+       // will clobber the test pattern created by the caller
+       ADD     $(1024 * 8), R15
+
+       // Ask signaller to setgid
+       MOVD    $·Baton(SB), R5
+       MOVW    $1, 0(R5)
+
+       // Wait for setgid completion
+loop:
+       SYNC
+       MOVW    Â·Baton(SB), R3
+       CMPBNE  R3, $0, loop
+
+       // Restore stack
+       SUB     $(1024 * 8), R15
+       RET
diff --git a/libgo/misc/cgo/test/issue9400/gccgo.go b/libgo/misc/cgo/test/issue9400/gccgo.go
new file mode 100644 (file)
index 0000000..0ef3a8c
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2014 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 gccgo
+
+package issue9400
+
+import (
+       "runtime"
+       "sync/atomic"
+)
+
+// The test for the gc compiler resets the stack pointer so that the
+// stack gets modified.  We don't have a way to do that for gccgo
+// without writing more assembly code, which we haven't bothered to
+// do.  So this is not much of a test.
+
+func RewindAndSetgid() {
+       atomic.StoreInt32(&Baton, 1)
+       for atomic.LoadInt32(&Baton) != 0 {
+               runtime.Gosched()
+       }
+}
diff --git a/libgo/misc/cgo/test/issue9400/stubs.go b/libgo/misc/cgo/test/issue9400/stubs.go
new file mode 100644 (file)
index 0000000..60193dc
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2014 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.
+
+package issue9400
+
+var Baton int32
+
+func RewindAndSetgid()
diff --git a/libgo/misc/cgo/test/issue9400_linux.go b/libgo/misc/cgo/test/issue9400_linux.go
new file mode 100644 (file)
index 0000000..34eb498
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright 2014 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.
+
+// Test that SIGSETXID runs on signal stack, since it's likely to
+// overflow if it runs on the Go stack.
+
+package cgotest
+
+/*
+#include <sys/types.h>
+#include <unistd.h>
+*/
+import "C"
+
+import (
+       "runtime"
+       "sync/atomic"
+       "testing"
+
+       "./issue9400"
+)
+
+func test9400(t *testing.T) {
+       // We synchronize through a shared variable, so we need two procs
+       defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
+
+       // Start signaller
+       atomic.StoreInt32(&issue9400.Baton, 0)
+       go func() {
+               // Wait for RewindAndSetgid
+               for atomic.LoadInt32(&issue9400.Baton) == 0 {
+                       runtime.Gosched()
+               }
+               // Broadcast SIGSETXID
+               runtime.LockOSThread()
+               C.setgid(0)
+               // Indicate that signalling is done
+               atomic.StoreInt32(&issue9400.Baton, 0)
+       }()
+
+       // Grow the stack and put down a test pattern
+       const pattern = 0x123456789abcdef
+       var big [1024]uint64 // len must match assmebly
+       for i := range big {
+               big[i] = pattern
+       }
+
+       // Temporarily rewind the stack and trigger SIGSETXID
+       issue9400.RewindAndSetgid()
+
+       // Check test pattern
+       for i := range big {
+               if big[i] != pattern {
+                       t.Fatalf("entry %d of test pattern is wrong; %#x != %#x", i, big[i], uint64(pattern))
+               }
+       }
+}
diff --git a/libgo/misc/cgo/test/issue9510.go b/libgo/misc/cgo/test/issue9510.go
new file mode 100644 (file)
index 0000000..efd3f77
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2015 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.
+
+// Test that we can link together two different cgo packages that both
+// use the same libgcc function.
+
+package cgotest
+
+import (
+       "runtime"
+       "testing"
+
+       "./issue9510a"
+       "./issue9510b"
+)
+
+func test9510(t *testing.T) {
+       if runtime.GOARCH == "arm" {
+               t.Skip("skipping because libgcc may be a Thumb library")
+       }
+       issue9510a.F(1, 1)
+       issue9510b.F(1, 1)
+}
diff --git a/libgo/misc/cgo/test/issue9510a/a.go b/libgo/misc/cgo/test/issue9510a/a.go
new file mode 100644 (file)
index 0000000..1a5224b
--- /dev/null
@@ -0,0 +1,15 @@
+package issue9510a
+
+/*
+static double csquare(double a, double b) {
+       __complex__ double d;
+       __real__ d = a;
+       __imag__ d = b;
+       return __real__ (d * d);
+}
+*/
+import "C"
+
+func F(a, b float64) float64 {
+       return float64(C.csquare(C.double(a), C.double(b)))
+}
diff --git a/libgo/misc/cgo/test/issue9510b/b.go b/libgo/misc/cgo/test/issue9510b/b.go
new file mode 100644 (file)
index 0000000..5016b39
--- /dev/null
@@ -0,0 +1,15 @@
+package issue9510b
+
+/*
+static double csquare(double a, double b) {
+       __complex__ double d;
+       __real__ d = a;
+       __imag__ d = b;
+       return __real__ (d * d);
+}
+*/
+import "C"
+
+func F(a, b float64) float64 {
+       return float64(C.csquare(C.double(a), C.double(b)))
+}
diff --git a/libgo/misc/cgo/test/issue9557.go b/libgo/misc/cgo/test/issue9557.go
new file mode 100644 (file)
index 0000000..4e8922a
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2015 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.
+
+// cgo rewrote C.var to *_Cvar_var, but left
+// C.var.field as _Cvar.var.field.  It now rewrites
+// the latter as (*_Cvar_var).field.
+// See https://golang.org/issue/9557.
+
+package cgotest
+
+// struct issue9557_t {
+//   int a;
+// } test9557bar = { 42 };
+//
+// struct issue9557_t *issue9557foo = &test9557bar;
+import "C"
+import "testing"
+
+func test9557(t *testing.T) {
+       // implicitly dereference a Go variable
+       foo := C.issue9557foo
+       if v := foo.a; v != 42 {
+               t.Fatalf("foo.a expected 42, but got %d", v)
+       }
+
+       // explicitly dereference a C variable
+       if v := (*C.issue9557foo).a; v != 42 {
+               t.Fatalf("(*C.issue9557foo).a expected 42, but is %d", v)
+       }
+
+       // implicitly dereference a C variable
+       if v := C.issue9557foo.a; v != 42 {
+               t.Fatalf("C.issue9557foo.a expected 42, but is %d", v)
+       }
+}
diff --git a/libgo/misc/cgo/test/setgid_linux.go b/libgo/misc/cgo/test/setgid_linux.go
new file mode 100644 (file)
index 0000000..6773f94
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2012 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.
+
+// Test that setgid does not hang on GNU/Linux.
+// See https://golang.org/issue/3871 for details.
+
+package cgotest
+
+/*
+#include <sys/types.h>
+#include <unistd.h>
+*/
+import "C"
+
+import (
+       "os"
+       "os/signal"
+       "syscall"
+       "testing"
+       "time"
+)
+
+func runTestSetgid() bool {
+       c := make(chan bool)
+       go func() {
+               C.setgid(0)
+               c <- true
+       }()
+       select {
+       case <-c:
+               return true
+       case <-time.After(5 * time.Second):
+               return false
+       }
+
+}
+
+func testSetgid(t *testing.T) {
+       if !runTestSetgid() {
+               t.Error("setgid hung")
+       }
+
+       // Now try it again after using signal.Notify.
+       signal.Notify(make(chan os.Signal, 1), syscall.SIGINT)
+       if !runTestSetgid() {
+               t.Error("setgid hung after signal.Notify")
+       }
+}
diff --git a/libgo/misc/cgo/test/sigaltstack.go b/libgo/misc/cgo/test/sigaltstack.go
new file mode 100644 (file)
index 0000000..2b7a1ec
--- /dev/null
@@ -0,0 +1,73 @@
+// Copyright 2015 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 !windows,!android
+
+// Test that the Go runtime still works if C code changes the signal stack.
+
+package cgotest
+
+/*
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static stack_t oss;
+static char signalStack[SIGSTKSZ];
+
+static void changeSignalStack(void) {
+       stack_t ss;
+       memset(&ss, 0, sizeof ss);
+       ss.ss_sp = signalStack;
+       ss.ss_flags = 0;
+       ss.ss_size = SIGSTKSZ;
+       if (sigaltstack(&ss, &oss) < 0) {
+               perror("sigaltstack");
+               abort();
+       }
+}
+
+static void restoreSignalStack(void) {
+#if (defined(__x86_64__) || defined(__i386__)) && defined(__APPLE__)
+       // The Darwin C library enforces a minimum that the kernel does not.
+       // This is OK since we allocated this much space in mpreinit,
+       // it was just removed from the buffer by stackalloc.
+       oss.ss_size = MINSIGSTKSZ;
+#endif
+       if (sigaltstack(&oss, NULL) < 0) {
+               perror("sigaltstack restore");
+               abort();
+       }
+}
+
+static int zero(void) {
+       return 0;
+}
+*/
+import "C"
+
+import (
+       "runtime"
+       "testing"
+)
+
+func testSigaltstack(t *testing.T) {
+       switch {
+       case runtime.GOOS == "solaris", runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64"):
+               t.Skipf("switching signal stack not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+       case runtime.GOOS == "darwin" && runtime.GOARCH == "386":
+               t.Skipf("sigaltstack fails on darwin/386")
+       }
+
+       C.changeSignalStack()
+       defer C.restoreSignalStack()
+       defer func() {
+               if recover() == nil {
+                       t.Error("did not see expected panic")
+               }
+       }()
+       v := 1 / int(C.zero())
+       t.Errorf("unexpected success of division by zero == %d", v)
+}
diff --git a/libgo/misc/cgo/test/sigprocmask.c b/libgo/misc/cgo/test/sigprocmask.c
new file mode 100644 (file)
index 0000000..bd99647
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2015 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 !windows
+
+#include <signal.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+extern void IntoGoAndBack();
+
+int CheckBlocked() {
+       sigset_t mask;
+       sigprocmask(SIG_BLOCK, NULL, &mask);
+       return sigismember(&mask, SIGIO);
+}
+
+static void* sigthreadfunc(void* unused) {
+       sigset_t mask;
+       sigemptyset(&mask);
+       sigaddset(&mask, SIGIO);
+       sigprocmask(SIG_BLOCK, &mask, NULL);
+       IntoGoAndBack();
+       return NULL;
+}
+
+int RunSigThread() {
+       pthread_t thread;
+       int r;
+
+       r = pthread_create(&thread, NULL, &sigthreadfunc, NULL);
+       if (r != 0)
+               return r;
+       return pthread_join(thread, NULL);
+}
diff --git a/libgo/misc/cgo/test/sigprocmask.go b/libgo/misc/cgo/test/sigprocmask.go
new file mode 100644 (file)
index 0000000..39b658e
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2015 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 !windows
+
+package cgotest
+
+/*
+#cgo CFLAGS: -pthread
+#cgo LDFLAGS: -pthread
+extern int RunSigThread();
+extern int CheckBlocked();
+*/
+import "C"
+import (
+       "os"
+       "os/signal"
+       "syscall"
+       "testing"
+)
+
+var blocked bool
+
+//export IntoGoAndBack
+func IntoGoAndBack() {
+       // Verify that SIGIO stays blocked on the C thread
+       // even when unblocked for signal.Notify().
+       signal.Notify(make(chan os.Signal), syscall.SIGIO)
+       blocked = C.CheckBlocked() != 0
+}
+
+func testSigprocmask(t *testing.T) {
+       if r := C.RunSigThread(); r != 0 {
+               t.Error("pthread_create/pthread_join failed")
+       }
+       if !blocked {
+               t.Error("Go runtime unblocked SIGIO")
+       }
+}
diff --git a/libgo/misc/cgo/testasan/main.go b/libgo/misc/cgo/testasan/main.go
new file mode 100644 (file)
index 0000000..1837c6c
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2013 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.
+
+package main
+
+/*
+#include <sys/mman.h>
+#include <pthread.h>
+#include <unistd.h>
+
+void ctor(void) __attribute__((constructor));
+static void* thread(void*);
+
+void
+ctor(void)
+{
+       // occupy memory where Go runtime would normally map heap
+       mmap((void*)0x00c000000000, 64<<10, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
+
+       // allocate 4K every 10us
+       pthread_t t;
+       pthread_create(&t, 0, thread, 0);
+}
+
+static void*
+thread(void *p)
+{
+       for(;;) {
+               usleep(10000);
+               mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+       }
+       return 0;
+}
+*/
+import "C"
+
+import (
+       "time"
+)
+
+func main() {
+       // ensure that we can function normally
+       var v [][]byte
+       for i := 0; i < 1000; i++ {
+               time.Sleep(10 * time.Microsecond)
+               v = append(v, make([]byte, 64<<10))
+       }
+}
diff --git a/libgo/misc/cgo/testcarchive/carchive_test.go b/libgo/misc/cgo/testcarchive/carchive_test.go
new file mode 100644 (file)
index 0000000..4999929
--- /dev/null
@@ -0,0 +1,540 @@
+// Copyright 2016 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.
+
+package carchive_test
+
+import (
+       "bufio"
+       "debug/elf"
+       "fmt"
+       "io/ioutil"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "strings"
+       "syscall"
+       "testing"
+       "time"
+       "unicode"
+)
+
+// Program to run.
+var bin []string
+
+// C compiler with args (from $(go env CC) $(go env GOGCCFLAGS)).
+var cc []string
+
+// An environment with GOPATH=$(pwd).
+var gopathEnv []string
+
+// ".exe" on Windows.
+var exeSuffix string
+
+var GOOS, GOARCH string
+var libgodir string
+
+func init() {
+       GOOS = goEnv("GOOS")
+       GOARCH = goEnv("GOARCH")
+       bin = cmdToRun("./testp")
+
+       ccOut := goEnv("CC")
+       cc = []string{string(ccOut)}
+
+       out := goEnv("GOGCCFLAGS")
+       quote := '\000'
+       start := 0
+       lastSpace := true
+       backslash := false
+       s := string(out)
+       for i, c := range s {
+               if quote == '\000' && unicode.IsSpace(c) {
+                       if !lastSpace {
+                               cc = append(cc, s[start:i])
+                               lastSpace = true
+                       }
+               } else {
+                       if lastSpace {
+                               start = i
+                               lastSpace = false
+                       }
+                       if quote == '\000' && !backslash && (c == '"' || c == '\'') {
+                               quote = c
+                               backslash = false
+                       } else if !backslash && quote == c {
+                               quote = '\000'
+                       } else if (quote == '\000' || quote == '"') && !backslash && c == '\\' {
+                               backslash = true
+                       } else {
+                               backslash = false
+                       }
+               }
+       }
+       if !lastSpace {
+               cc = append(cc, s[start:])
+       }
+
+       if GOOS == "darwin" {
+               // For Darwin/ARM.
+               // TODO(crawshaw): can we do better?
+               cc = append(cc, []string{"-framework", "CoreFoundation", "-framework", "Foundation"}...)
+       }
+       libgodir = GOOS + "_" + GOARCH
+       switch GOOS {
+       case "darwin":
+               if GOARCH == "arm" || GOARCH == "arm64" {
+                       libgodir += "_shared"
+               }
+       case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
+               libgodir += "_shared"
+       }
+       cc = append(cc, "-I", filepath.Join("pkg", libgodir))
+
+       // Build an environment with GOPATH=$(pwd)
+       env := os.Environ()
+       var n []string
+       for _, e := range env {
+               if !strings.HasPrefix(e, "GOPATH=") {
+                       n = append(n, e)
+               }
+       }
+       dir, err := os.Getwd()
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(2)
+       }
+       n = append(n, "GOPATH="+dir)
+       gopathEnv = n
+
+       if GOOS == "windows" {
+               exeSuffix = ".exe"
+       }
+}
+
+func goEnv(key string) string {
+       out, err := exec.Command("go", "env", key).Output()
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "go env %s failed:\n%s", key, err)
+               fmt.Fprintf(os.Stderr, "%s", err.(*exec.ExitError).Stderr)
+               os.Exit(2)
+       }
+       return strings.TrimSpace(string(out))
+}
+
+func cmdToRun(name string) []string {
+       execScript := "go_" + goEnv("GOOS") + "_" + goEnv("GOARCH") + "_exec"
+       executor, err := exec.LookPath(execScript)
+       if err != nil {
+               return []string{name}
+       }
+       return []string{executor, name}
+}
+
+func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) {
+       cmd := exec.Command(buildcmd[0], buildcmd[1:]...)
+       cmd.Env = gopathEnv
+       if out, err := cmd.CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+       defer func() {
+               os.Remove(libgoa)
+               os.Remove(libgoh)
+       }()
+
+       ccArgs := append(cc, "-o", exe, "main.c")
+       if GOOS == "windows" {
+               ccArgs = append(ccArgs, "main_windows.c", libgoa, "-lntdll", "-lws2_32", "-lwinmm")
+       } else {
+               ccArgs = append(ccArgs, "main_unix.c", libgoa)
+       }
+       t.Log(ccArgs)
+       if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+       defer os.Remove(exe)
+
+       binArgs := append(cmdToRun(exe), "arg1", "arg2")
+       if out, err := exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+}
+
+func TestInstall(t *testing.T) {
+       defer os.RemoveAll("pkg")
+
+       testInstall(t, "./testp1"+exeSuffix,
+               filepath.Join("pkg", libgodir, "libgo.a"),
+               filepath.Join("pkg", libgodir, "libgo.h"),
+               "go", "install", "-buildmode=c-archive", "libgo")
+
+       // Test building libgo other than installing it.
+       // Header files are now present.
+       testInstall(t, "./testp2"+exeSuffix, "libgo.a", "libgo.h",
+               "go", "build", "-buildmode=c-archive", filepath.Join("src", "libgo", "libgo.go"))
+
+       testInstall(t, "./testp3"+exeSuffix, "libgo.a", "libgo.h",
+               "go", "build", "-buildmode=c-archive", "-o", "libgo.a", "libgo")
+}
+
+func TestEarlySignalHandler(t *testing.T) {
+       switch GOOS {
+       case "darwin":
+               switch GOARCH {
+               case "arm", "arm64":
+                       t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH)
+               }
+       case "windows":
+               t.Skip("skipping signal test on Windows")
+       }
+
+       defer func() {
+               os.Remove("libgo2.a")
+               os.Remove("libgo2.h")
+               os.Remove("testp")
+               os.RemoveAll("pkg")
+       }()
+
+       cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "libgo2")
+       cmd.Env = gopathEnv
+       if out, err := cmd.CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+
+       ccArgs := append(cc, "-o", "testp"+exeSuffix, "main2.c", "libgo2.a")
+       if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+
+       if out, err := exec.Command(bin[0], bin[1:]...).CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+}
+
+func TestSignalForwarding(t *testing.T) {
+       switch GOOS {
+       case "darwin":
+               switch GOARCH {
+               case "arm", "arm64":
+                       t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH)
+               }
+       case "windows":
+               t.Skip("skipping signal test on Windows")
+       }
+
+       defer func() {
+               os.Remove("libgo2.a")
+               os.Remove("libgo2.h")
+               os.Remove("testp")
+               os.RemoveAll("pkg")
+       }()
+
+       cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "libgo2")
+       cmd.Env = gopathEnv
+       if out, err := cmd.CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+
+       ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a")
+       if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+
+       cmd = exec.Command(bin[0], append(bin[1:], "1")...)
+
+       out, err := cmd.CombinedOutput()
+
+       if err == nil {
+               t.Logf("%s", out)
+               t.Error("test program succeeded unexpectedly")
+       } else if ee, ok := err.(*exec.ExitError); !ok {
+               t.Logf("%s", out)
+               t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err)
+       } else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok {
+               t.Logf("%s", out)
+               t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys())
+       } else if !ws.Signaled() || ws.Signal() != syscall.SIGSEGV {
+               t.Logf("%s", out)
+               t.Errorf("got %v; expected SIGSEGV", ee)
+       }
+}
+
+func TestSignalForwardingExternal(t *testing.T) {
+       switch GOOS {
+       case "darwin":
+               switch GOARCH {
+               case "arm", "arm64":
+                       t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH)
+               }
+       case "windows":
+               t.Skip("skipping signal test on Windows")
+       }
+
+       defer func() {
+               os.Remove("libgo2.a")
+               os.Remove("libgo2.h")
+               os.Remove("testp")
+               os.RemoveAll("pkg")
+       }()
+
+       cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "libgo2")
+       cmd.Env = gopathEnv
+       if out, err := cmd.CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+
+       ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a")
+       if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+
+       // We want to send the process a signal and see if it dies.
+       // Normally the signal goes to the C thread, the Go signal
+       // handler picks it up, sees that it is running in a C thread,
+       // and the program dies. Unfortunately, occasionally the
+       // signal is delivered to a Go thread, which winds up
+       // discarding it because it was sent by another program and
+       // there is no Go handler for it. To avoid this, run the
+       // program several times in the hopes that it will eventually
+       // fail.
+       const tries = 20
+       for i := 0; i < tries; i++ {
+               cmd = exec.Command(bin[0], append(bin[1:], "2")...)
+
+               stderr, err := cmd.StderrPipe()
+               if err != nil {
+                       t.Fatal(err)
+               }
+               defer stderr.Close()
+
+               r := bufio.NewReader(stderr)
+
+               err = cmd.Start()
+
+               if err != nil {
+                       t.Fatal(err)
+               }
+
+               // Wait for trigger to ensure that the process is started.
+               ok, err := r.ReadString('\n')
+
+               // Verify trigger.
+               if err != nil || ok != "OK\n" {
+                       t.Fatalf("Did not receive OK signal")
+               }
+
+               // Give the program a chance to enter the sleep function.
+               time.Sleep(time.Millisecond)
+
+               cmd.Process.Signal(syscall.SIGSEGV)
+
+               err = cmd.Wait()
+
+               if err == nil {
+                       continue
+               }
+
+               if ee, ok := err.(*exec.ExitError); !ok {
+                       t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err)
+               } else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok {
+                       t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys())
+               } else if !ws.Signaled() || ws.Signal() != syscall.SIGSEGV {
+                       t.Errorf("got %v; expected SIGSEGV", ee)
+               } else {
+                       // We got the error we expected.
+                       return
+               }
+       }
+
+       t.Errorf("program succeeded unexpectedly %d times", tries)
+}
+
+func TestOsSignal(t *testing.T) {
+       switch GOOS {
+       case "windows":
+               t.Skip("skipping signal test on Windows")
+       }
+
+       defer func() {
+               os.Remove("libgo3.a")
+               os.Remove("libgo3.h")
+               os.Remove("testp")
+               os.RemoveAll("pkg")
+       }()
+
+       cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo3.a", "libgo3")
+       cmd.Env = gopathEnv
+       if out, err := cmd.CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+
+       ccArgs := append(cc, "-o", "testp"+exeSuffix, "main3.c", "libgo3.a")
+       if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+
+       if out, err := exec.Command(bin[0], bin[1:]...).CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+}
+
+func TestSigaltstack(t *testing.T) {
+       switch GOOS {
+       case "windows":
+               t.Skip("skipping signal test on Windows")
+       }
+
+       defer func() {
+               os.Remove("libgo4.a")
+               os.Remove("libgo4.h")
+               os.Remove("testp")
+               os.RemoveAll("pkg")
+       }()
+
+       cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo4.a", "libgo4")
+       cmd.Env = gopathEnv
+       if out, err := cmd.CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+
+       ccArgs := append(cc, "-o", "testp"+exeSuffix, "main4.c", "libgo4.a")
+       if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+
+       if out, err := exec.Command(bin[0], bin[1:]...).CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+}
+
+const testar = `#!/usr/bin/env bash
+while expr $1 : '[-]' >/dev/null; do
+  shift
+done
+echo "testar" > $1
+echo "testar" > PWD/testar.ran
+`
+
+func TestExtar(t *testing.T) {
+       switch GOOS {
+       case "windows":
+               t.Skip("skipping signal test on Windows")
+       }
+
+       defer func() {
+               os.Remove("libgo4.a")
+               os.Remove("libgo4.h")
+               os.Remove("testar")
+               os.Remove("testar.ran")
+               os.RemoveAll("pkg")
+       }()
+
+       os.Remove("testar")
+       dir, err := os.Getwd()
+       if err != nil {
+               t.Fatal(err)
+       }
+       s := strings.Replace(testar, "PWD", dir, 1)
+       if err := ioutil.WriteFile("testar", []byte(s), 0777); err != nil {
+               t.Fatal(err)
+       }
+
+       cmd := exec.Command("go", "build", "-buildmode=c-archive", "-ldflags=-extar="+filepath.Join(dir, "testar"), "-o", "libgo4.a", "libgo4")
+       cmd.Env = gopathEnv
+       if out, err := cmd.CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+
+       if _, err := os.Stat("testar.ran"); err != nil {
+               if os.IsNotExist(err) {
+                       t.Error("testar does not exist after go build")
+               } else {
+                       t.Errorf("error checking testar: %v", err)
+               }
+       }
+}
+
+func TestPIE(t *testing.T) {
+       switch GOOS {
+       case "windows", "darwin", "plan9":
+               t.Skipf("skipping PIE test on %s", GOOS)
+       }
+
+       defer func() {
+               os.Remove("testp" + exeSuffix)
+               os.RemoveAll("pkg")
+       }()
+
+       cmd := exec.Command("go", "install", "-buildmode=c-archive", "libgo")
+       cmd.Env = gopathEnv
+       if out, err := cmd.CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+
+       ccArgs := append(cc, "-fPIE", "-pie", "-o", "testp"+exeSuffix, "main.c", "main_unix.c", filepath.Join("pkg", libgodir, "libgo.a"))
+       if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+
+       binArgs := append(bin, "arg1", "arg2")
+       if out, err := exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput(); err != nil {
+               t.Logf("%s", out)
+               t.Fatal(err)
+       }
+
+       f, err := elf.Open("testp" + exeSuffix)
+       if err != nil {
+               t.Fatal("elf.Open failed: ", err)
+       }
+       defer f.Close()
+       if hasDynTag(t, f, elf.DT_TEXTREL) {
+               t.Errorf("%s has DT_TEXTREL flag", "testp"+exeSuffix)
+       }
+}
+
+func hasDynTag(t *testing.T, f *elf.File, tag elf.DynTag) bool {
+       ds := f.SectionByType(elf.SHT_DYNAMIC)
+       if ds == nil {
+               t.Error("no SHT_DYNAMIC section")
+               return false
+       }
+       d, err := ds.Data()
+       if err != nil {
+               t.Errorf("can't read SHT_DYNAMIC contents: %v", err)
+               return false
+       }
+       for len(d) > 0 {
+               var t elf.DynTag
+               switch f.Class {
+               case elf.ELFCLASS32:
+                       t = elf.DynTag(f.ByteOrder.Uint32(d[:4]))
+                       d = d[8:]
+               case elf.ELFCLASS64:
+                       t = elf.DynTag(f.ByteOrder.Uint64(d[:8]))
+                       d = d[16:]
+               }
+               if t == tag {
+                       return true
+               }
+       }
+       return false
+}
diff --git a/libgo/misc/cgo/testcarchive/main.c b/libgo/misc/cgo/testcarchive/main.c
new file mode 100644 (file)
index 0000000..163b539
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2015 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.
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "p.h"
+#include "libgo.h"
+
+extern int install_handler();
+extern int check_handler();
+
+int main(void) {
+       int32_t res;
+
+       int r1 = install_handler();
+       if (r1!=0) {
+               return r1;
+       }
+
+       if (!DidInitRun()) {
+               fprintf(stderr, "ERROR: buildmode=c-archive init should run\n");
+               return 2;
+       }
+
+       if (DidMainRun()) {
+               fprintf(stderr, "ERROR: buildmode=c-archive should not run main\n");
+               return 2;
+       }
+
+       int r2 = check_handler();
+       if (r2!=0) {
+               return r2;
+       }
+
+       res = FromPkg();
+       if (res != 1024) {
+               fprintf(stderr, "ERROR: FromPkg()=%d, want 1024\n", res);
+               return 2;
+       }
+
+       CheckArgs();
+
+       fprintf(stderr, "PASS\n");
+       return 0;
+}
diff --git a/libgo/misc/cgo/testcarchive/main2.c b/libgo/misc/cgo/testcarchive/main2.c
new file mode 100644 (file)
index 0000000..774e014
--- /dev/null
@@ -0,0 +1,199 @@
+// Copyright 2015 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.
+
+// Test installing a signal handler before the Go code starts.
+// This is a lot like misc/cgo/testcshared/main4.c.
+
+#include <setjmp.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sched.h>
+#include <time.h>
+
+#include "libgo2.h"
+
+static void die(const char* msg) {
+       perror(msg);
+       exit(EXIT_FAILURE);
+}
+
+static volatile sig_atomic_t sigioSeen;
+
+// Use up some stack space.
+static void recur(int i, char *p) {
+       char a[1024];
+
+       *p = '\0';
+       if (i > 0) {
+               recur(i - 1, a);
+       }
+}
+
+// Signal handler that uses up more stack space than a goroutine will have.
+static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
+       char a[1024];
+
+       recur(4, a);
+       sigioSeen = 1;
+}
+
+static jmp_buf jmp;
+static char* nullPointer;
+
+// An arbitrary function which requires proper stack alignment; see
+// http://golang.org/issue/17641.
+static void callWithVarargs(void* dummy, ...) {
+       va_list args;
+       va_start(args, dummy);
+       va_end(args);
+}
+
+// Signal handler for SIGSEGV on a C thread.
+static void segvHandler(int signo, siginfo_t* info, void* ctxt) {
+       sigset_t mask;
+       int i;
+
+       // Call an arbitrary function that requires the stack to be properly aligned.
+       callWithVarargs("dummy arg", 3.1415);
+
+       if (sigemptyset(&mask) < 0) {
+               die("sigemptyset");
+       }
+       if (sigaddset(&mask, SIGSEGV) < 0) {
+               die("sigaddset");
+       }
+       i = sigprocmask(SIG_UNBLOCK, &mask, NULL);
+       if (i != 0) {
+               fprintf(stderr, "sigprocmask: %s\n", strerror(i));
+               exit(EXIT_FAILURE);
+       }
+
+       // Don't try this at home.
+       longjmp(jmp, signo);
+
+       // We should never get here.
+       abort();
+}
+
+// Set up the signal handlers in a high priority constructor,
+// so that they are installed before the Go code starts.
+
+static void init(void) __attribute__ ((constructor (200)));
+
+static void init() {
+       struct sigaction sa;
+
+       memset(&sa, 0, sizeof sa);
+       sa.sa_sigaction = ioHandler;
+       if (sigemptyset(&sa.sa_mask) < 0) {
+               die("sigemptyset");
+       }
+       sa.sa_flags = SA_SIGINFO;
+       if (sigaction(SIGIO, &sa, NULL) < 0) {
+               die("sigaction");
+       }
+
+       sa.sa_sigaction = segvHandler;
+       if (sigaction(SIGSEGV, &sa, NULL) < 0 || sigaction(SIGBUS, &sa, NULL) < 0) {
+               die("sigaction");
+       }
+
+}
+
+int main(int argc, char** argv) {
+       int verbose;
+       sigset_t mask;
+       int i;
+       struct timespec ts;
+
+       verbose = argc > 1;
+       setvbuf(stdout, NULL, _IONBF, 0);
+
+       // Call setsid so that we can use kill(0, SIGIO) below.
+       // Don't check the return value so that this works both from
+       // a job control shell and from a shell script.
+       setsid();
+
+       if (verbose) {
+               printf("calling RunGoroutines\n");
+       }
+
+       RunGoroutines();
+
+       // Block SIGIO in this thread to make it more likely that it
+       // will be delivered to a goroutine.
+
+       if (verbose) {
+               printf("calling pthread_sigmask\n");
+       }
+
+       if (sigemptyset(&mask) < 0) {
+               die("sigemptyset");
+       }
+       if (sigaddset(&mask, SIGIO) < 0) {
+               die("sigaddset");
+       }
+       i = pthread_sigmask(SIG_BLOCK, &mask, NULL);
+       if (i != 0) {
+               fprintf(stderr, "pthread_sigmask: %s\n", strerror(i));
+               exit(EXIT_FAILURE);
+       }
+
+       if (verbose) {
+               printf("calling kill\n");
+       }
+
+       if (kill(0, SIGIO) < 0) {
+               die("kill");
+       }
+
+       if (verbose) {
+               printf("waiting for sigioSeen\n");
+       }
+
+       // Wait until the signal has been delivered.
+       i = 0;
+       while (!sigioSeen) {
+               ts.tv_sec = 0;
+               ts.tv_nsec = 1000000;
+               nanosleep(&ts, NULL);
+               i++;
+               if (i > 5000) {
+                       fprintf(stderr, "looping too long waiting for signal\n");
+                       exit(EXIT_FAILURE);
+               }
+       }
+
+       if (verbose) {
+               printf("calling setjmp\n");
+       }
+
+       // Test that a SIGSEGV on this thread is delivered to us.
+       if (setjmp(jmp) == 0) {
+               if (verbose) {
+                       printf("triggering SIGSEGV\n");
+               }
+
+               *nullPointer = '\0';
+
+               fprintf(stderr, "continued after address error\n");
+               exit(EXIT_FAILURE);
+       }
+
+       if (verbose) {
+               printf("calling TestSEGV\n");
+       }
+
+       TestSEGV();
+
+       printf("PASS\n");
+       return 0;
+}
diff --git a/libgo/misc/cgo/testcarchive/main3.c b/libgo/misc/cgo/testcarchive/main3.c
new file mode 100644 (file)
index 0000000..0a6c0d3
--- /dev/null
@@ -0,0 +1,155 @@
+// Copyright 2015 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.
+
+// Test os/signal.Notify and os/signal.Reset.
+// This is a lot like misc/cgo/testcshared/main5.c.
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sched.h>
+
+#include "libgo3.h"
+
+static void die(const char* msg) {
+       perror(msg);
+       exit(EXIT_FAILURE);
+}
+
+static volatile sig_atomic_t sigioSeen;
+
+static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
+       sigioSeen = 1;
+}
+
+int main(int argc, char** argv) {
+       int verbose;
+       struct sigaction sa;
+       int i;
+       struct timespec ts;
+
+       verbose = argc > 2;
+       setvbuf(stdout, NULL, _IONBF, 0);
+
+       if (verbose) {
+               printf("calling sigaction\n");
+       }
+
+       memset(&sa, 0, sizeof sa);
+       sa.sa_sigaction = ioHandler;
+       if (sigemptyset(&sa.sa_mask) < 0) {
+               die("sigemptyset");
+       }
+       sa.sa_flags = SA_SIGINFO;
+       if (sigaction(SIGIO, &sa, NULL) < 0) {
+               die("sigaction");
+       }
+
+       // At this point there should not be a Go signal handler
+       // installed for SIGIO.
+
+       if (verbose) {
+               printf("raising SIGIO\n");
+       }
+
+       if (raise(SIGIO) < 0) {
+               die("raise");
+       }
+
+       if (verbose) {
+               printf("waiting for sigioSeen\n");
+       }
+
+       // Wait until the signal has been delivered.
+       i = 0;
+       while (!sigioSeen) {
+               ts.tv_sec = 0;
+               ts.tv_nsec = 1000000;
+               nanosleep(&ts, NULL);
+               i++;
+               if (i > 5000) {
+                       fprintf(stderr, "looping too long waiting for signal\n");
+                       exit(EXIT_FAILURE);
+               }
+       }
+
+       sigioSeen = 0;
+
+       // Tell the Go code to catch SIGIO.
+
+       if (verbose) {
+               printf("calling CatchSIGIO\n");
+       }
+
+       CatchSIGIO();
+
+       if (verbose) {
+               printf("raising SIGIO\n");
+       }
+
+       if (raise(SIGIO) < 0) {
+               die("raise");
+       }
+
+       if (verbose) {
+               printf("calling SawSIGIO\n");
+       }
+
+       if (!SawSIGIO()) {
+               fprintf(stderr, "Go handler did not see SIGIO\n");
+               exit(EXIT_FAILURE);
+       }
+
+       if (sigioSeen != 0) {
+               fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n");
+               exit(EXIT_FAILURE);
+       }
+
+       // Tell the Go code to stop catching SIGIO.
+
+       if (verbose) {
+               printf("calling ResetSIGIO\n");
+       }
+
+       ResetSIGIO();
+
+       if (verbose) {
+               printf("raising SIGIO\n");
+       }
+
+       if (raise(SIGIO) < 0) {
+               die("raise");
+       }
+
+       if (verbose) {
+               printf("calling SawSIGIO\n");
+       }
+
+       if (SawSIGIO()) {
+               fprintf(stderr, "Go handler saw SIGIO after Reset\n");
+               exit(EXIT_FAILURE);
+       }
+
+       if (verbose) {
+               printf("waiting for sigioSeen\n");
+       }
+
+       // Wait until the signal has been delivered.
+       i = 0;
+       while (!sigioSeen) {
+               ts.tv_sec = 0;
+               ts.tv_nsec = 1000000;
+               nanosleep(&ts, NULL);
+               i++;
+               if (i > 5000) {
+                       fprintf(stderr, "looping too long waiting for signal\n");
+                       exit(EXIT_FAILURE);
+               }
+       }
+
+       printf("PASS\n");
+       return 0;
+}
diff --git a/libgo/misc/cgo/testcarchive/main4.c b/libgo/misc/cgo/testcarchive/main4.c
new file mode 100644 (file)
index 0000000..4fd55e7
--- /dev/null
@@ -0,0 +1,197 @@
+// Copyright 2015 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.
+
+// Test a C thread that calls sigaltstack and then calls Go code.
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sched.h>
+#include <pthread.h>
+
+#include "libgo4.h"
+
+static void die(const char* msg) {
+       perror(msg);
+       exit(EXIT_FAILURE);
+}
+
+static int ok = 1;
+
+static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
+}
+
+// Set up the SIGIO signal handler in a high priority constructor, so
+// that it is installed before the Go code starts.
+
+static void init(void) __attribute__ ((constructor (200)));
+
+static void init() {
+       struct sigaction sa;
+
+       memset(&sa, 0, sizeof sa);
+       sa.sa_sigaction = ioHandler;
+       if (sigemptyset(&sa.sa_mask) < 0) {
+               die("sigemptyset");
+       }
+       sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
+       if (sigaction(SIGIO, &sa, NULL) < 0) {
+               die("sigaction");
+       }
+}
+
+// Test raising SIGIO on a C thread with an alternate signal stack
+// when there is a Go signal handler for SIGIO.
+static void* thread1(void* arg __attribute__ ((unused))) {
+       stack_t ss;
+       int i;
+       stack_t nss;
+       struct timespec ts;
+
+       // Set up an alternate signal stack for this thread.
+       memset(&ss, 0, sizeof ss);
+       ss.ss_sp = malloc(SIGSTKSZ);
+       if (ss.ss_sp == NULL) {
+               die("malloc");
+       }
+       ss.ss_flags = 0;
+       ss.ss_size = SIGSTKSZ;
+       if (sigaltstack(&ss, NULL) < 0) {
+               die("sigaltstack");
+       }
+
+       // Send ourselves a SIGIO.  This will be caught by the Go
+       // signal handler which should forward to the C signal
+       // handler.
+       i = pthread_kill(pthread_self(), SIGIO);
+       if (i != 0) {
+               fprintf(stderr, "pthread_kill: %s\n", strerror(i));
+               exit(EXIT_FAILURE);
+       }
+
+       // Wait until the signal has been delivered.
+       i = 0;
+       while (SIGIOCount() == 0) {
+               ts.tv_sec = 0;
+               ts.tv_nsec = 1000000;
+               nanosleep(&ts, NULL);
+               i++;
+               if (i > 5000) {
+                       fprintf(stderr, "looping too long waiting for signal\n");
+                       exit(EXIT_FAILURE);
+               }
+       }
+
+       // We should still be on the same signal stack.
+       if (sigaltstack(NULL, &nss) < 0) {
+               die("sigaltstack check");
+       }
+       if ((nss.ss_flags & SS_DISABLE) != 0) {
+               fprintf(stderr, "sigaltstack disabled on return from Go\n");
+               ok = 0;
+       } else if (nss.ss_sp != ss.ss_sp) {
+               fprintf(stderr, "sigalstack changed on return from Go\n");
+               ok = 0;
+       }
+
+       return NULL;
+}
+
+// Test calling a Go function to raise SIGIO on a C thread with an
+// alternate signal stack when there is a Go signal handler for SIGIO.
+static void* thread2(void* arg __attribute__ ((unused))) {
+       stack_t ss;
+       int i;
+       int oldcount;
+       pthread_t tid;
+       struct timespec ts;
+       stack_t nss;
+
+       // Set up an alternate signal stack for this thread.
+       memset(&ss, 0, sizeof ss);
+       ss.ss_sp = malloc(SIGSTKSZ);
+       if (ss.ss_sp == NULL) {
+               die("malloc");
+       }
+       ss.ss_flags = 0;
+       ss.ss_size = SIGSTKSZ;
+       if (sigaltstack(&ss, NULL) < 0) {
+               die("sigaltstack");
+       }
+
+       oldcount = SIGIOCount();
+
+       // Call a Go function that will call a C function to send us a
+       // SIGIO.
+       tid = pthread_self();
+       GoRaiseSIGIO(&tid);
+
+       // Wait until the signal has been delivered.
+       i = 0;
+       while (SIGIOCount() == oldcount) {
+               ts.tv_sec = 0;
+               ts.tv_nsec = 1000000;
+               nanosleep(&ts, NULL);
+               i++;
+               if (i > 5000) {
+                       fprintf(stderr, "looping too long waiting for signal\n");
+                       exit(EXIT_FAILURE);
+               }
+       }
+
+       // We should still be on the same signal stack.
+       if (sigaltstack(NULL, &nss) < 0) {
+               die("sigaltstack check");
+       }
+       if ((nss.ss_flags & SS_DISABLE) != 0) {
+               fprintf(stderr, "sigaltstack disabled on return from Go\n");
+               ok = 0;
+       } else if (nss.ss_sp != ss.ss_sp) {
+               fprintf(stderr, "sigalstack changed on return from Go\n");
+               ok = 0;
+       }
+
+       return NULL;
+}
+
+int main(int argc, char **argv) {
+       pthread_t tid;
+       int i;
+
+       // Tell the Go library to start looking for SIGIO.
+       GoCatchSIGIO();
+
+       i = pthread_create(&tid, NULL, thread1, NULL);
+       if (i != 0) {
+               fprintf(stderr, "pthread_create: %s\n", strerror(i));
+               exit(EXIT_FAILURE);
+       }
+
+       i = pthread_join(tid, NULL);
+       if (i != 0) {
+               fprintf(stderr, "pthread_join: %s\n", strerror(i));
+               exit(EXIT_FAILURE);
+       }
+
+       i = pthread_create(&tid, NULL, thread2, NULL);
+       if (i != 0) {
+               fprintf(stderr, "pthread_create: %s\n", strerror(i));
+               exit(EXIT_FAILURE);
+       }
+
+       i = pthread_join(tid, NULL);
+       if (i != 0) {
+               fprintf(stderr, "pthread_join: %s\n", strerror(i));
+               exit(EXIT_FAILURE);
+       }
+
+       if (!ok) {
+               exit(EXIT_FAILURE);
+       }
+
+       printf("PASS\n");
+       return 0;
+}
diff --git a/libgo/misc/cgo/testcarchive/main5.c b/libgo/misc/cgo/testcarchive/main5.c
new file mode 100644 (file)
index 0000000..9fadf08
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright 2015 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.
+
+// Test for verifying that the Go runtime properly forwards
+// signals when non-Go signals are raised.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/select.h>
+
+#include "libgo2.h"
+
+int main(int argc, char** argv) {
+       int verbose;
+       int test;
+
+       if (argc < 2) {
+               printf("Missing argument\n");
+               return 1;
+       }
+
+       test = atoi(argv[1]);
+
+       verbose = (argc > 2);
+
+       if (verbose) {
+               printf("calling RunGoroutines\n");
+       }
+
+       Noop();
+
+       switch (test) {
+               case 1: {
+                       if (verbose) {
+                               printf("attempting segfault\n");
+                       }
+
+                       volatile int crash = *(int *) 0;
+                       break;
+               }
+
+               case 2: {
+                       struct timeval tv;
+
+                       if (verbose) {
+                               printf("attempting external signal test\n");
+                       }
+
+                       fprintf(stderr, "OK\n");
+                       fflush(stderr);
+
+                       // The program should be interrupted before
+                       // this sleep finishes. We use select rather
+                       // than sleep because in older versions of
+                       // glibc the sleep function does some signal
+                       // fiddling to handle SIGCHLD.  If this
+                       // program is fiddling signals just when the
+                       // test program sends the signal, the signal
+                       // may be delivered to a Go thread which will
+                       // break this test.
+                       tv.tv_sec = 60;
+                       tv.tv_usec = 0;
+                       select(0, NULL, NULL, NULL, &tv);
+
+                       break;
+               }
+               default:
+                       printf("Unknown test: %d\n", test);
+                       return 0;
+       }
+
+       printf("FAIL\n");
+       return 0;
+}
diff --git a/libgo/misc/cgo/testcarchive/main_unix.c b/libgo/misc/cgo/testcarchive/main_unix.c
new file mode 100644 (file)
index 0000000..4d9d16f
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright 2015 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.
+
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+struct sigaction sa;
+struct sigaction osa;
+
+static void (*oldHandler)(int, siginfo_t*, void*);
+
+static void handler(int signo, siginfo_t* info, void* ctxt) {
+       if (oldHandler) {
+               oldHandler(signo, info, ctxt);
+       }
+}
+
+int install_handler() {
+       // Install our own signal handler.
+       memset(&sa, 0, sizeof sa);
+       sa.sa_sigaction = handler;
+       sigemptyset(&sa.sa_mask);
+       sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
+       memset(&osa, 0, sizeof osa);
+       sigemptyset(&osa.sa_mask);
+       if (sigaction(SIGSEGV, &sa, &osa) < 0) {
+               perror("sigaction");
+               return 2;
+       }
+       if (osa.sa_handler == SIG_DFL || (osa.sa_flags&SA_ONSTACK) == 0) {
+               fprintf(stderr, "Go runtime did not install signal handler\n");
+               return 2;
+       }
+       oldHandler = osa.sa_sigaction;
+
+       return 0;
+}
+
+int check_handler() {
+       if (sigaction(SIGSEGV, NULL, &sa) < 0) {
+               perror("sigaction check");
+               return 2;
+       }
+       if (sa.sa_sigaction != handler) {
+               fprintf(stderr, "ERROR: wrong signal handler: %p != %p\n", sa.sa_sigaction, handler);
+               return 2;
+       }
+       return 0;
+}
+
diff --git a/libgo/misc/cgo/testcarchive/main_windows.c b/libgo/misc/cgo/testcarchive/main_windows.c
new file mode 100644 (file)
index 0000000..eded8af
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2015 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.
+
+/*
+ * Dummy implementations for Windows, because Windows doesn't
+ * support Unix-style signal handling.
+ */
+
+int install_handler() {
+       return 0;
+}
+
+
+int check_handler() {
+       return 0;
+}
diff --git a/libgo/misc/cgo/testcarchive/src/libgo/libgo.go b/libgo/misc/cgo/testcarchive/src/libgo/libgo.go
new file mode 100644 (file)
index 0000000..45958a5
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright 2015 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.
+
+package main
+
+import (
+       "fmt"
+       "os"
+       "syscall"
+       "time"
+
+       _ "p"
+)
+
+import "C"
+
+var initCh = make(chan int, 1)
+var ranMain bool
+
+func init() {
+       // emulate an exceedingly slow package initialization function
+       time.Sleep(100 * time.Millisecond)
+       initCh <- 42
+}
+
+func main() { ranMain = true }
+
+//export DidInitRun
+func DidInitRun() bool {
+       select {
+       case x := <-initCh:
+               if x != 42 {
+                       // Just in case initCh was not correctly made.
+                       println("want init value of 42, got: ", x)
+                       syscall.Exit(2)
+               }
+               return true
+       default:
+               return false
+       }
+}
+
+//export DidMainRun
+func DidMainRun() bool { return ranMain }
+
+//export CheckArgs
+func CheckArgs() {
+       if len(os.Args) != 3 || os.Args[1] != "arg1" || os.Args[2] != "arg2" {
+               fmt.Printf("CheckArgs: want [_, arg1, arg2], got: %v\n", os.Args)
+               os.Exit(2)
+       }
+}
diff --git a/libgo/misc/cgo/testcarchive/src/libgo2/libgo2.go b/libgo/misc/cgo/testcarchive/src/libgo2/libgo2.go
new file mode 100644 (file)
index 0000000..fbed493
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2015 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.
+
+package main
+
+import "C"
+
+import (
+       "fmt"
+       "os"
+       "runtime"
+)
+
+// RunGoroutines starts some goroutines that don't do anything.
+// The idea is to get some threads going, so that a signal will be delivered
+// to a thread started by Go.
+//export RunGoroutines
+func RunGoroutines() {
+       for i := 0; i < 4; i++ {
+               go func() {
+                       runtime.LockOSThread()
+                       select {}
+               }()
+       }
+}
+
+var P *byte
+
+// TestSEGV makes sure that an invalid address turns into a run-time Go panic.
+//export TestSEGV
+func TestSEGV() {
+       defer func() {
+               if recover() == nil {
+                       fmt.Fprintln(os.Stderr, "no panic from segv")
+                       os.Exit(1)
+               }
+       }()
+       *P = 0
+       fmt.Fprintln(os.Stderr, "continued after segv")
+       os.Exit(1)
+}
+
+// Noop ensures that the Go runtime is initialized.
+//export Noop
+func Noop() {
+}
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testcarchive/src/libgo3/libgo3.go b/libgo/misc/cgo/testcarchive/src/libgo3/libgo3.go
new file mode 100644 (file)
index 0000000..94e5d21
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2015 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.
+
+package main
+
+import "C"
+
+import (
+       "os"
+       "os/signal"
+       "syscall"
+       "time"
+)
+
+// The channel used to read SIGIO signals.
+var sigioChan chan os.Signal
+
+// CatchSIGIO starts catching SIGIO signals.
+//export CatchSIGIO
+func CatchSIGIO() {
+       sigioChan = make(chan os.Signal, 1)
+       signal.Notify(sigioChan, syscall.SIGIO)
+}
+
+// ResetSIGIO stops catching SIGIO signals.
+//export ResetSIGIO
+func ResetSIGIO() {
+       signal.Reset(syscall.SIGIO)
+}
+
+// SawSIGIO returns whether we saw a SIGIO within a brief pause.
+//export SawSIGIO
+func SawSIGIO() C.int {
+       select {
+       case <-sigioChan:
+               return 1
+       case <-time.After(100 * time.Millisecond):
+               return 0
+       }
+}
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testcarchive/src/libgo4/libgo4.go b/libgo/misc/cgo/testcarchive/src/libgo4/libgo4.go
new file mode 100644 (file)
index 0000000..8cc1895
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright 2015 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.
+
+package main
+
+/*
+#include <signal.h>
+#include <pthread.h>
+
+// Raise SIGIO.
+static void CRaiseSIGIO(pthread_t* p) {
+       pthread_kill(*p, SIGIO);
+}
+*/
+import "C"
+
+import (
+       "os"
+       "os/signal"
+       "sync/atomic"
+       "syscall"
+)
+
+var sigioCount int32
+
+// Catch SIGIO.
+//export GoCatchSIGIO
+func GoCatchSIGIO() {
+       c := make(chan os.Signal, 1)
+       signal.Notify(c, syscall.SIGIO)
+       go func() {
+               for range c {
+                       atomic.AddInt32(&sigioCount, 1)
+               }
+       }()
+}
+
+// Raise SIGIO.
+//export GoRaiseSIGIO
+func GoRaiseSIGIO(p *C.pthread_t) {
+       C.CRaiseSIGIO(p)
+}
+
+// Return the number of SIGIO signals seen.
+//export SIGIOCount
+func SIGIOCount() C.int {
+       return C.int(atomic.LoadInt32(&sigioCount))
+}
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testcarchive/src/p/p.go b/libgo/misc/cgo/testcarchive/src/p/p.go
new file mode 100644 (file)
index 0000000..82b445c
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2015 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.
+
+package p
+
+import "C"
+
+//export FromPkg
+func FromPkg() int32 { return 1024 }
diff --git a/libgo/misc/cgo/testcshared/main0.c b/libgo/misc/cgo/testcshared/main0.c
new file mode 100644 (file)
index 0000000..1274b89
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2015 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.
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include "p.h"
+#include "libgo.h"
+
+// Tests libgo.so to export the following functions.
+//   int8_t DidInitRun();
+//   int8_t DidMainRun();
+//   int32_t FromPkg();
+int main(void) {
+  int8_t ran_init = DidInitRun();
+  if (!ran_init) {
+    fprintf(stderr, "ERROR: DidInitRun returned unexpected results: %d\n",
+            ran_init);
+    return 1;
+  }
+  int8_t ran_main = DidMainRun();
+  if (ran_main) {
+    fprintf(stderr, "ERROR: DidMainRun returned unexpected results: %d\n",
+            ran_main);
+    return 1;
+  }
+  int32_t from_pkg = FromPkg();
+  if (from_pkg != 1024) {
+    fprintf(stderr, "ERROR: FromPkg=%d, want %d\n", from_pkg, 1024);
+    return 1;
+  }
+  // test.bash looks for "PASS" to ensure this program has reached the end. 
+  printf("PASS\n");
+  return 0;
+}
diff --git a/libgo/misc/cgo/testcshared/main1.c b/libgo/misc/cgo/testcshared/main1.c
new file mode 100644 (file)
index 0000000..420dd1e
--- /dev/null
@@ -0,0 +1,69 @@
+// Copyright 2015 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.
+
+#include <stdint.h>
+#include <stdio.h>
+#include <dlfcn.h>
+
+int check_int8(void* handle, const char* fname, int8_t want) {
+  int8_t (*fn)();
+  fn = (int8_t (*)())dlsym(handle, fname);
+  if (!fn) {
+    fprintf(stderr, "ERROR: missing %s: %s\n", fname, dlerror());
+    return 1;
+  }
+  signed char ret = fn();
+  if (ret != want) {
+    fprintf(stderr, "ERROR: %s=%d, want %d\n", fname, ret, want);
+    return 1;
+  }
+  return 0;
+}
+
+int check_int32(void* handle, const char* fname, int32_t want) {
+  int32_t (*fn)();
+  fn = (int32_t (*)())dlsym(handle, fname);
+  if (!fn) {
+    fprintf(stderr, "ERROR: missing %s: %s\n", fname, dlerror());
+    return 1;
+  }
+  int32_t ret = fn();
+  if (ret != want) {
+    fprintf(stderr, "ERROR: %s=%d, want %d\n", fname, ret, want);
+    return 1;
+  }
+  return 0;
+}
+
+// Tests libgo.so to export the following functions.
+//   int8_t DidInitRun() // returns true
+//   int8_t DidMainRun() // returns true
+//   int32_t FromPkg() // returns 1024
+int main(int argc, char** argv) {
+  void* handle = dlopen(argv[1], RTLD_LAZY | RTLD_GLOBAL);
+  if (!handle) {
+    fprintf(stderr, "ERROR: failed to open the shared library: %s\n",
+                   dlerror());
+    return 2;
+  }
+
+  int ret = 0;
+  ret = check_int8(handle, "DidInitRun", 1);
+  if (ret != 0) {
+    return ret;
+  }
+
+  ret = check_int8(handle, "DidMainRun", 0);
+  if (ret != 0) {
+    return ret;
+  }
+
+  ret = check_int32(handle, "FromPkg", 1024);
+  if (ret != 0) {
+   return ret;
+  }
+  // test.bash looks for "PASS" to ensure this program has reached the end. 
+  printf("PASS\n");
+  return 0;
+}
diff --git a/libgo/misc/cgo/testcshared/main2.c b/libgo/misc/cgo/testcshared/main2.c
new file mode 100644 (file)
index 0000000..6e8bf14
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright 2015 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.
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#define fd (100)
+
+// Tests libgo2.so, which does not export any functions.
+// Read a string from the file descriptor and print it.
+int main(void) {
+  int i;
+  ssize_t n;
+  char buf[20];
+  struct timespec ts;
+
+  // The descriptor will be initialized in a thread, so we have to
+  // give a chance to get opened.
+  for (i = 0; i < 1000; i++) {
+    n = read(fd, buf, sizeof buf);
+    if (n >= 0)
+      break;
+    if (errno != EBADF && errno != EINVAL) {
+      fprintf(stderr, "BUG: read: %s\n", strerror(errno));
+      return 2;
+    }
+
+    // An EBADF error means that the shared library has not opened the
+    // descriptor yet.
+    ts.tv_sec = 0;
+    ts.tv_nsec = 1000000;
+    nanosleep(&ts, NULL);
+  }
+
+  if (n < 0) {
+    fprintf(stderr, "BUG: failed to read any data from pipe\n");
+    return 2;
+  }
+
+  if (n == 0) {
+    fprintf(stderr, "BUG: unexpected EOF\n");
+    return 2;
+  }
+
+  if (n == sizeof buf) {
+    n--;
+  }
+  buf[n] = '\0';
+  printf("%s\n", buf);
+  return 0;
+}
diff --git a/libgo/misc/cgo/testcshared/main3.c b/libgo/misc/cgo/testcshared/main3.c
new file mode 100644 (file)
index 0000000..49cc055
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2015 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.
+
+#include <stdint.h>
+#include <stdio.h>
+#include <dlfcn.h>
+
+// Tests "main.main" is exported on android/arm,
+// which golang.org/x/mobile/app depends on.
+int main(int argc, char** argv) {
+  void* handle = dlopen(argv[1], RTLD_LAZY | RTLD_GLOBAL);
+  if (!handle) {
+    fprintf(stderr, "ERROR: failed to open the shared library: %s\n",
+            dlerror());
+    return 2;
+  }
+
+  uintptr_t main_fn = (uintptr_t)dlsym(handle, "main.main");
+  if (!main_fn) {
+    fprintf(stderr, "ERROR: missing main.main: %s\n", dlerror());
+    return 2;
+  }
+
+  // TODO(hyangah): check that main.main can run.
+
+  printf("PASS\n");
+  return 0;
+}
diff --git a/libgo/misc/cgo/testcshared/main4.c b/libgo/misc/cgo/testcshared/main4.c
new file mode 100644 (file)
index 0000000..355cdef
--- /dev/null
@@ -0,0 +1,215 @@
+// Copyright 2015 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.
+
+// Test that a signal handler that uses up stack space does not crash
+// if the signal is delivered to a thread running a goroutine.
+// This is a lot like misc/cgo/testcarchive/main2.c.
+
+#include <setjmp.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sched.h>
+#include <time.h>
+#include <dlfcn.h>
+
+static void die(const char* msg) {
+       perror(msg);
+       exit(EXIT_FAILURE);
+}
+
+static volatile sig_atomic_t sigioSeen;
+
+// Use up some stack space.
+static void recur(int i, char *p) {
+       char a[1024];
+
+       *p = '\0';
+       if (i > 0) {
+               recur(i - 1, a);
+       }
+}
+
+// Signal handler that uses up more stack space than a goroutine will have.
+static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
+       char a[1024];
+
+       recur(4, a);
+       sigioSeen = 1;
+}
+
+static jmp_buf jmp;
+static char* nullPointer;
+
+// Signal handler for SIGSEGV on a C thread.
+static void segvHandler(int signo, siginfo_t* info, void* ctxt) {
+       sigset_t mask;
+       int i;
+
+       if (sigemptyset(&mask) < 0) {
+               die("sigemptyset");
+       }
+       if (sigaddset(&mask, SIGSEGV) < 0) {
+               die("sigaddset");
+       }
+       i = sigprocmask(SIG_UNBLOCK, &mask, NULL);
+       if (i != 0) {
+               fprintf(stderr, "sigprocmask: %s\n", strerror(i));
+               exit(EXIT_FAILURE);
+       }
+
+       // Don't try this at home.
+       longjmp(jmp, signo);
+
+       // We should never get here.
+       abort();
+}
+
+int main(int argc, char** argv) {
+       int verbose;
+       struct sigaction sa;
+       void* handle;
+       void (*fn)(void);
+       sigset_t mask;
+       int i;
+       struct timespec ts;
+
+       verbose = argc > 2;
+       setvbuf(stdout, NULL, _IONBF, 0);
+
+       // Call setsid so that we can use kill(0, SIGIO) below.
+       // Don't check the return value so that this works both from
+       // a job control shell and from a shell script.
+       setsid();
+
+       if (verbose) {
+               printf("calling sigaction\n");
+       }
+
+       memset(&sa, 0, sizeof sa);
+       sa.sa_sigaction = ioHandler;
+       if (sigemptyset(&sa.sa_mask) < 0) {
+               die("sigemptyset");
+       }
+       sa.sa_flags = SA_SIGINFO;
+       if (sigaction(SIGIO, &sa, NULL) < 0) {
+               die("sigaction");
+       }
+
+       sa.sa_sigaction = segvHandler;
+       if (sigaction(SIGSEGV, &sa, NULL) < 0 || sigaction(SIGBUS, &sa, NULL) < 0) {
+               die("sigaction");
+       }
+
+       if (verbose) {
+               printf("calling dlopen\n");
+       }
+
+       handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL);
+       if (handle == NULL) {
+               fprintf(stderr, "%s\n", dlerror());
+               exit(EXIT_FAILURE);
+       }
+
+       if (verbose) {
+               printf("calling dlsym\n");
+       }
+
+       // Start some goroutines.
+       fn = (void(*)(void))dlsym(handle, "RunGoroutines");
+       if (fn == NULL) {
+               fprintf(stderr, "%s\n", dlerror());
+               exit(EXIT_FAILURE);
+       }
+
+       if (verbose) {
+               printf("calling RunGoroutines\n");
+       }
+
+       fn();
+
+       // Block SIGIO in this thread to make it more likely that it
+       // will be delivered to a goroutine.
+
+       if (verbose) {
+               printf("calling pthread_sigmask\n");
+       }
+
+       if (sigemptyset(&mask) < 0) {
+               die("sigemptyset");
+       }
+       if (sigaddset(&mask, SIGIO) < 0) {
+               die("sigaddset");
+       }
+       i = pthread_sigmask(SIG_BLOCK, &mask, NULL);
+       if (i != 0) {
+               fprintf(stderr, "pthread_sigmask: %s\n", strerror(i));
+               exit(EXIT_FAILURE);
+       }
+
+       if (verbose) {
+               printf("calling kill\n");
+       }
+
+       if (kill(0, SIGIO) < 0) {
+               die("kill");
+       }
+
+       if (verbose) {
+               printf("waiting for sigioSeen\n");
+       }
+
+       // Wait until the signal has been delivered.
+       i = 0;
+       while (!sigioSeen) {
+               ts.tv_sec = 0;
+               ts.tv_nsec = 1000000;
+               nanosleep(&ts, NULL);
+               i++;
+               if (i > 5000) {
+                       fprintf(stderr, "looping too long waiting for signal\n");
+                       exit(EXIT_FAILURE);
+               }
+       }
+
+       if (verbose) {
+               printf("calling setjmp\n");
+       }
+
+       // Test that a SIGSEGV on this thread is delivered to us.
+       if (setjmp(jmp) == 0) {
+               if (verbose) {
+                       printf("triggering SIGSEGV\n");
+               }
+
+               *nullPointer = '\0';
+
+               fprintf(stderr, "continued after address error\n");
+               exit(EXIT_FAILURE);
+       }
+
+       if (verbose) {
+               printf("calling dlsym\n");
+       }
+
+       // Make sure that a SIGSEGV in Go causes a run-time panic.
+       fn = (void (*)(void))dlsym(handle, "TestSEGV");
+       if (fn == NULL) {
+               fprintf(stderr, "%s\n", dlerror());
+               exit(EXIT_FAILURE);
+       }
+
+       if (verbose) {
+               printf("calling TestSEGV\n");
+       }
+
+       fn();
+
+       printf("PASS\n");
+       return 0;
+}
diff --git a/libgo/misc/cgo/testcshared/main5.c b/libgo/misc/cgo/testcshared/main5.c
new file mode 100644 (file)
index 0000000..1bc9910
--- /dev/null
@@ -0,0 +1,199 @@
+// Copyright 2015 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.
+
+// Test that a signal handler works in non-Go code when using
+// os/signal.Notify.
+// This is a lot like misc/cgo/testcarchive/main3.c.
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sched.h>
+#include <dlfcn.h>
+
+static void die(const char* msg) {
+       perror(msg);
+       exit(EXIT_FAILURE);
+}
+
+static volatile sig_atomic_t sigioSeen;
+
+static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
+       sigioSeen = 1;
+}
+
+int main(int argc, char** argv) {
+       int verbose;
+       struct sigaction sa;
+       void* handle;
+       void (*fn1)(void);
+       int (*sawSIGIO)(void);
+       int i;
+       struct timespec ts;
+
+       verbose = argc > 2;
+       setvbuf(stdout, NULL, _IONBF, 0);
+
+       if (verbose) {
+               printf("calling sigaction\n");
+       }
+
+       memset(&sa, 0, sizeof sa);
+       sa.sa_sigaction = ioHandler;
+       if (sigemptyset(&sa.sa_mask) < 0) {
+               die("sigemptyset");
+       }
+       sa.sa_flags = SA_SIGINFO;
+       if (sigaction(SIGIO, &sa, NULL) < 0) {
+               die("sigaction");
+       }
+
+       if (verbose) {
+               printf("calling dlopen\n");
+       }
+
+       handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL);
+       if (handle == NULL) {
+               fprintf(stderr, "%s\n", dlerror());
+               exit(EXIT_FAILURE);
+       }
+
+       // At this point there should not be a Go signal handler
+       // installed for SIGIO.
+
+       if (verbose) {
+               printf("raising SIGIO\n");
+       }
+
+       if (raise(SIGIO) < 0) {
+               die("raise");
+       }
+
+       if (verbose) {
+               printf("waiting for sigioSeen\n");
+       }
+
+       // Wait until the signal has been delivered.
+       i = 0;
+       while (!sigioSeen) {
+               ts.tv_sec = 0;
+               ts.tv_nsec = 1000000;
+               nanosleep(&ts, NULL);
+               i++;
+               if (i > 5000) {
+                       fprintf(stderr, "looping too long waiting for signal\n");
+                       exit(EXIT_FAILURE);
+               }
+       }
+
+       sigioSeen = 0;
+
+       // Tell the Go code to catch SIGIO.
+
+       if (verbose) {
+               printf("calling dlsym\n");
+       }
+
+       fn1 = (void(*)(void))dlsym(handle, "CatchSIGIO");
+       if (fn1 == NULL) {
+               fprintf(stderr, "%s\n", dlerror());
+               exit(EXIT_FAILURE);
+       }
+
+       if (verbose) {
+               printf("calling CatchSIGIO\n");
+       }
+
+       fn1();
+
+       if (verbose) {
+               printf("raising SIGIO\n");
+       }
+
+       if (raise(SIGIO) < 0) {
+               die("raise");
+       }
+
+       if (verbose) {
+               printf("calling dlsym\n");
+       }
+
+       // Check that the Go code saw SIGIO.
+       sawSIGIO = (int (*)(void))dlsym(handle, "SawSIGIO");
+       if (sawSIGIO == NULL) {
+               fprintf(stderr, "%s\n", dlerror());
+               exit(EXIT_FAILURE);
+       }
+
+       if (verbose) {
+               printf("calling SawSIGIO\n");
+       }
+
+       if (!sawSIGIO()) {
+               fprintf(stderr, "Go handler did not see SIGIO\n");
+               exit(EXIT_FAILURE);
+       }
+
+       if (sigioSeen != 0) {
+               fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n");
+               exit(EXIT_FAILURE);
+       }
+
+       // Tell the Go code to stop catching SIGIO.
+
+       if (verbose) {
+               printf("calling dlsym\n");
+       }
+
+       fn1 = (void(*)(void))dlsym(handle, "ResetSIGIO");
+       if (fn1 == NULL) {
+               fprintf(stderr, "%s\n", dlerror());
+               exit(EXIT_FAILURE);
+       }
+
+       if (verbose) {
+               printf("calling ResetSIGIO\n");
+       }
+
+       fn1();
+
+       if (verbose) {
+               printf("raising SIGIO\n");
+       }
+
+       if (raise(SIGIO) < 0) {
+               die("raise");
+       }
+
+       if (verbose) {
+               printf("calling SawSIGIO\n");
+       }
+
+       if (sawSIGIO()) {
+               fprintf(stderr, "Go handler saw SIGIO after Reset\n");
+               exit(EXIT_FAILURE);
+       }
+
+       if (verbose) {
+               printf("waiting for sigioSeen\n");
+       }
+
+       // Wait until the signal has been delivered.
+       i = 0;
+       while (!sigioSeen) {
+               ts.tv_sec = 0;
+               ts.tv_nsec = 1000000;
+               nanosleep(&ts, NULL);
+               i++;
+               if (i > 5000) {
+                       fprintf(stderr, "looping too long waiting for signal\n");
+                       exit(EXIT_FAILURE);
+               }
+       }
+
+       printf("PASS\n");
+       return 0;
+}
diff --git a/libgo/misc/cgo/testcshared/src/libgo/libgo.go b/libgo/misc/cgo/testcshared/src/libgo/libgo.go
new file mode 100644 (file)
index 0000000..8a4bf79
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2015 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.
+
+package main
+
+import (
+       _ "p"
+       "syscall"
+       "time"
+)
+
+import "C"
+
+var initCh = make(chan int, 1)
+var ranMain bool
+
+func init() {
+       // emulate an exceedingly slow package initialization function
+       time.Sleep(100 * time.Millisecond)
+       initCh <- 42
+}
+
+func main() {
+       ranMain = true
+}
+
+//export DidInitRun
+func DidInitRun() bool {
+       select {
+       case x := <-initCh:
+               if x != 42 {
+                       // Just in case initCh was not correctly made.
+                       println("want init value of 42, got: ", x)
+                       syscall.Exit(2)
+               }
+               return true
+       default:
+               return false
+       }
+}
+
+//export DidMainRun
+func DidMainRun() bool {
+       return ranMain
+}
diff --git a/libgo/misc/cgo/testcshared/src/libgo2/dup2.go b/libgo/misc/cgo/testcshared/src/libgo2/dup2.go
new file mode 100644 (file)
index 0000000..d18f0b1
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2015 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 darwin dragonfly freebsd linux,!arm64 netbsd openbsd
+
+package main
+
+import "syscall"
+
+func dup2(oldfd, newfd int) error {
+       return syscall.Dup2(oldfd, newfd)
+}
diff --git a/libgo/misc/cgo/testcshared/src/libgo2/dup3.go b/libgo/misc/cgo/testcshared/src/libgo2/dup3.go
new file mode 100644 (file)
index 0000000..c9c65a6
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2015 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 linux,arm64
+
+package main
+
+import "syscall"
+
+func dup2(oldfd, newfd int) error {
+       return syscall.Dup3(oldfd, newfd, 0)
+}
diff --git a/libgo/misc/cgo/testcshared/src/libgo2/libgo2.go b/libgo/misc/cgo/testcshared/src/libgo2/libgo2.go
new file mode 100644 (file)
index 0000000..1b69d8f
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright 2015 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 darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package main
+
+// Test a shared library created by -buildmode=c-shared that does not
+// export anything.
+
+import (
+       "fmt"
+       "os"
+       "syscall"
+)
+
+// To test this we want to communicate between the main program and
+// the shared library without using any exported symbols.  The init
+// function creates a pipe and Dups the read end to a known number
+// that the C code can also use.
+
+const (
+       fd = 100
+)
+
+func init() {
+       var p [2]int
+       if e := syscall.Pipe(p[0:]); e != nil {
+               fmt.Fprintf(os.Stderr, "pipe: %v\n", e)
+               os.Exit(2)
+       }
+
+       if e := dup2(p[0], fd); e != nil {
+               fmt.Fprintf(os.Stderr, "dup2: %v\n", e)
+               os.Exit(2)
+       }
+
+       const str = "PASS"
+       if n, e := syscall.Write(p[1], []byte(str)); e != nil || n != len(str) {
+               fmt.Fprintf(os.Stderr, "write: %d %v\n", n, e)
+               os.Exit(2)
+       }
+
+       if e := syscall.Close(p[1]); e != nil {
+               fmt.Fprintf(os.Stderr, "close: %v\n", e)
+               os.Exit(2)
+       }
+}
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testcshared/src/libgo4/libgo4.go b/libgo/misc/cgo/testcshared/src/libgo4/libgo4.go
new file mode 100644 (file)
index 0000000..ab40b75
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright 2015 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.
+
+package main
+
+import "C"
+
+import (
+       "fmt"
+       "os"
+       "runtime"
+)
+
+// RunGoroutines starts some goroutines that don't do anything.
+// The idea is to get some threads going, so that a signal will be delivered
+// to a thread started by Go.
+//export RunGoroutines
+func RunGoroutines() {
+       for i := 0; i < 4; i++ {
+               go func() {
+                       runtime.LockOSThread()
+                       select {}
+               }()
+       }
+}
+
+var P *byte
+
+// TestSEGV makes sure that an invalid address turns into a run-time Go panic.
+//export TestSEGV
+func TestSEGV() {
+       defer func() {
+               if recover() == nil {
+                       fmt.Fprintln(os.Stderr, "no panic from segv")
+                       os.Exit(1)
+               }
+       }()
+       *P = 0
+       fmt.Fprintln(os.Stderr, "continued after segv")
+       os.Exit(1)
+}
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testcshared/src/libgo5/libgo5.go b/libgo/misc/cgo/testcshared/src/libgo5/libgo5.go
new file mode 100644 (file)
index 0000000..94e5d21
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2015 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.
+
+package main
+
+import "C"
+
+import (
+       "os"
+       "os/signal"
+       "syscall"
+       "time"
+)
+
+// The channel used to read SIGIO signals.
+var sigioChan chan os.Signal
+
+// CatchSIGIO starts catching SIGIO signals.
+//export CatchSIGIO
+func CatchSIGIO() {
+       sigioChan = make(chan os.Signal, 1)
+       signal.Notify(sigioChan, syscall.SIGIO)
+}
+
+// ResetSIGIO stops catching SIGIO signals.
+//export ResetSIGIO
+func ResetSIGIO() {
+       signal.Reset(syscall.SIGIO)
+}
+
+// SawSIGIO returns whether we saw a SIGIO within a brief pause.
+//export SawSIGIO
+func SawSIGIO() C.int {
+       select {
+       case <-sigioChan:
+               return 1
+       case <-time.After(100 * time.Millisecond):
+               return 0
+       }
+}
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testcshared/src/p/p.go b/libgo/misc/cgo/testcshared/src/p/p.go
new file mode 100644 (file)
index 0000000..82b445c
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2015 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.
+
+package p
+
+import "C"
+
+//export FromPkg
+func FromPkg() int32 { return 1024 }
diff --git a/libgo/misc/cgo/testcshared/test.bash b/libgo/misc/cgo/testcshared/test.bash
new file mode 100644 (file)
index 0000000..0315fb0
--- /dev/null
@@ -0,0 +1,193 @@
+#!/usr/bin/env bash
+# Copyright 2015 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.
+
+# For testing Android, this script requires adb to push and run compiled
+# binaries on a target device.
+
+set -e
+
+if [ ! -f src/libgo/libgo.go ]; then
+       cwd=$(pwd)
+       echo "misc/cgo/testcshared/test.bash is running in $cwd" 1>&2
+       exit 1
+fi
+
+goos=$(go env GOOS)
+goarch=$(go env GOARCH)
+goroot=$(go env GOROOT)
+if [ ! -d "$goroot" ]; then
+       echo 'misc/cgo/testcshared/test.bash cannot find GOROOT' 1>&2
+       echo '$GOROOT:' "$GOROOT" 1>&2
+       echo 'go env GOROOT:' "$goroot" 1>&2
+       exit 1
+fi
+
+# Directory where cgo headers and outputs will be installed.
+# The installation directory format varies depending on the platform.
+installdir=pkg/${goos}_${goarch}_testcshared_shared
+if [ "${goos}" == "darwin" ]; then
+       installdir=pkg/${goos}_${goarch}_testcshared
+fi
+
+# Temporary directory on the android device.
+androidpath=/data/local/tmp/testcshared-$$
+
+function cleanup() {
+       rm -f libgo.$libext libgo2.$libext libgo4.$libext libgo5.$libext
+       rm -f libgo.h libgo4.h libgo5.h
+       rm -f testp testp2 testp3 testp4 testp5
+       rm -rf pkg "${goroot}/${installdir}"
+
+       if [ "$goos" == "android" ]; then
+               adb shell rm -rf "$androidpath"
+       fi
+}
+trap cleanup EXIT
+
+if [ "$goos" == "android" ]; then
+       adb shell mkdir -p "$androidpath"
+fi
+
+function run() {
+       case "$goos" in
+       "android")
+               local args=$@
+               output=$(adb shell "cd ${androidpath}; $@")
+               output=$(echo $output|tr -d '\r')
+               case $output in
+                       *PASS) echo "PASS";; 
+                       *) echo "$output";;
+               esac
+               ;;
+       *)
+               echo $(env $@)
+               ;;
+       esac
+}
+
+function binpush() {
+       bin=${1}
+       if [ "$goos" == "android" ]; then
+               adb push "$bin"  "${androidpath}/${bin}" 2>/dev/null
+       fi
+}
+
+rm -rf pkg
+
+suffix="-installsuffix testcshared"
+
+libext="so"
+if [ "$goos" == "darwin" ]; then
+       libext="dylib"
+fi
+
+# Create the header files.
+GOPATH=$(pwd) go install -buildmode=c-shared $suffix libgo
+
+GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo.$libext src/libgo/libgo.go
+binpush libgo.$libext
+
+if [ "$goos" == "linux" ] || [ "$goos" == "android" ] ; then
+    if readelf -d libgo.$libext | grep TEXTREL >/dev/null; then
+        echo "libgo.$libext has TEXTREL set"
+        exit 1
+    fi
+fi
+
+GOGCCFLAGS=$(go env GOGCCFLAGS)
+if [ "$goos" == "android" ]; then
+       GOGCCFLAGS="${GOGCCFLAGS} -pie"
+fi
+
+status=0
+
+# test0: exported symbols in shared lib are accessible.
+# TODO(iant): using _shared here shouldn't really be necessary.
+$(go env CC) ${GOGCCFLAGS} -I ${installdir} -o testp main0.c ./libgo.$libext
+binpush testp
+
+output=$(run LD_LIBRARY_PATH=. ./testp)
+if [ "$output" != "PASS" ]; then
+       echo "FAIL test0 got ${output}"
+       status=1
+fi
+
+# test1: shared library can be dynamically loaded and exported symbols are accessible.
+$(go env CC) ${GOGCCFLAGS} -o testp main1.c -ldl
+binpush testp
+output=$(run ./testp ./libgo.$libext)
+if [ "$output" != "PASS" ]; then
+       echo "FAIL test1 got ${output}"
+       status=1
+fi
+
+# test2: tests libgo2 which does not export any functions.
+GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo2.$libext libgo2
+binpush libgo2.$libext
+linkflags="-Wl,--no-as-needed"
+if [ "$goos" == "darwin" ]; then
+       linkflags=""
+fi
+$(go env CC) ${GOGCCFLAGS} -o testp2 main2.c $linkflags libgo2.$libext
+binpush testp2
+output=$(run LD_LIBRARY_PATH=. ./testp2)
+if [ "$output" != "PASS" ]; then
+       echo "FAIL test2 got ${output}"
+       status=1
+fi
+
+# test3: tests main.main is exported on android.
+if [ "$goos" == "android" ]; then
+       $(go env CC) ${GOGCCFLAGS} -o testp3 main3.c -ldl
+       binpush testp3
+       output=$(run ./testp ./libgo.so)
+       if [ "$output" != "PASS" ]; then
+               echo "FAIL test3 got ${output}"
+               status=1
+       fi
+fi
+
+# test4: tests signal handlers
+GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo4.$libext libgo4
+binpush libgo4.$libext
+$(go env CC) ${GOGCCFLAGS} -pthread -o testp4 main4.c -ldl
+binpush testp4
+output=$(run ./testp4 ./libgo4.$libext 2>&1)
+if test "$output" != "PASS"; then
+    echo "FAIL test4 got ${output}"
+    if test "$goos" != "android"; then
+       echo "re-running test4 in verbose mode"
+       ./testp4 ./libgo4.$libext verbose
+    fi
+    status=1
+fi
+
+# test5: tests signal handlers with os/signal.Notify
+GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo5.$libext libgo5
+binpush libgo5.$libext
+$(go env CC) ${GOGCCFLAGS} -pthread -o testp5 main5.c -ldl
+binpush testp5
+output=$(run ./testp5 ./libgo5.$libext 2>&1)
+if test "$output" != "PASS"; then
+    echo "FAIL test5 got ${output}"
+    if test "$goos" != "android"; then
+       echo "re-running test5 in verbose mode"
+       ./testp5 ./libgo5.$libext verbose
+    fi
+    status=1
+fi
+
+if test "$libext" = "dylib"; then
+       # make sure dylibs are well-formed
+       if ! otool -l libgo*.dylib >/dev/null; then
+               status=1
+       fi
+fi
+
+if test $status = 0; then
+    echo "ok"
+fi
+
+exit $status
diff --git a/libgo/misc/cgo/testgodefs/anonunion.go b/libgo/misc/cgo/testgodefs/anonunion.go
new file mode 100644 (file)
index 0000000..18840f2
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2014 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 ignore
+
+package main
+
+// This file tests that when cgo -godefs sees a struct with a field
+// that is an anonymous union, the first field in the union is
+// promoted to become a field of the struct.  See issue 6677 for
+// background.
+
+/*
+typedef struct {
+       union {
+               long l;
+               int c;
+       };
+} t;
+*/
+import "C"
+
+// Input for cgo -godefs.
+
+type T C.t
diff --git a/libgo/misc/cgo/testgodefs/issue8478.go b/libgo/misc/cgo/testgodefs/issue8478.go
new file mode 100644 (file)
index 0000000..2321446
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2014 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 ignore
+
+package main
+
+// Issue 8478.  Test that void* is consistently mapped to *byte.
+
+/*
+typedef struct {
+       void *p;
+       void **q;
+       void ***r;
+} s;
+*/
+import "C"
+
+type Issue8478 C.s
diff --git a/libgo/misc/cgo/testgodefs/main.go b/libgo/misc/cgo/testgodefs/main.go
new file mode 100644 (file)
index 0000000..1ce0fd0
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2014 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.
+
+package main
+
+// Test that the struct field in anonunion.go was promoted.
+var v1 T
+var v2 = v1.L
+
+// Test that P, Q, and R all point to byte.
+var v3 = Issue8478{P: (*byte)(nil), Q: (**byte)(nil), R: (***byte)(nil)}
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testgodefs/test.bash b/libgo/misc/cgo/testgodefs/test.bash
new file mode 100644 (file)
index 0000000..a82ff93
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# Copyright 2014 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.
+
+# We are testing cgo -godefs, which translates Go files that use
+# import "C" into Go files with Go definitions of types defined in the
+# import "C" block.  Add more tests here.
+FILE_PREFIXES="anonunion issue8478"
+
+RM=
+for FP in $FILE_PREFIXES
+do
+  go tool cgo -godefs -srcdir . ${FP}.go > ${FP}_defs.go
+  RM="${RM} ${FP}_defs.go"
+done
+
+go build . && ./testgodefs
+EXIT=$?
+rm -rf _obj testgodefs ${RM}
+exit $EXIT
diff --git a/libgo/misc/cgo/testplugin/altpath/src/common/common.go b/libgo/misc/cgo/testplugin/altpath/src/common/common.go
new file mode 100644 (file)
index 0000000..505ba02
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2016 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.
+
+package common
+
+var X int
+
+func init() {
+       X = 4
+}
diff --git a/libgo/misc/cgo/testplugin/altpath/src/plugin-mismatch/main.go b/libgo/misc/cgo/testplugin/altpath/src/plugin-mismatch/main.go
new file mode 100644 (file)
index 0000000..8aacafc
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2016 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.
+
+package main
+
+// // No C code required.
+import "C"
+
+// The common package imported here does not match the common package
+// imported by plugin1. A program that attempts to load plugin1 and
+// plugin-mismatch should produce an error.
+import "common"
+
+func ReadCommonX() int {
+       return common.X
+}
diff --git a/libgo/misc/cgo/testplugin/src/common/common.go b/libgo/misc/cgo/testplugin/src/common/common.go
new file mode 100644 (file)
index 0000000..b064e6b
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2016 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.
+
+package common
+
+var X int
+
+func init() {
+       X = 3
+}
diff --git a/libgo/misc/cgo/testplugin/src/host/host.go b/libgo/misc/cgo/testplugin/src/host/host.go
new file mode 100644 (file)
index 0000000..898f44e
--- /dev/null
@@ -0,0 +1,148 @@
+// Copyright 2016 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.
+
+package main
+
+import (
+       "fmt"
+       "log"
+       "path/filepath"
+       "plugin"
+       "strings"
+
+       "common"
+)
+
+func init() {
+       common.X *= 5
+}
+
+// testUnnamed tests that two plugins built with .go files passed on
+// the command line do not have overlapping symbols. That is,
+// unnamed1.so/FuncInt and unnamed2.so/FuncInt should be distinct functions.
+func testUnnamed() {
+       p, err := plugin.Open("unnamed1.so")
+       if err != nil {
+               log.Fatalf(`plugin.Open("unnamed1.so"): %v`, err)
+       }
+       fn, err := p.Lookup("FuncInt")
+       if err != nil {
+               log.Fatalf(`unnamed1.so: Lookup("FuncInt") failed: %v`, err)
+       }
+       if got, want := fn.(func() int)(), 1; got != want {
+               log.Fatalf("unnamed1.so: FuncInt()=%d, want %d", got, want)
+       }
+
+       p, err = plugin.Open("unnamed2.so")
+       if err != nil {
+               log.Fatalf(`plugin.Open("unnamed2.so"): %v`, err)
+       }
+       fn, err = p.Lookup("FuncInt")
+       if err != nil {
+               log.Fatalf(`unnamed2.so: Lookup("FuncInt") failed: %v`, err)
+       }
+       if got, want := fn.(func() int)(), 2; got != want {
+               log.Fatalf("unnamed2.so: FuncInt()=%d, want %d", got, want)
+       }
+}
+
+func main() {
+       if got, want := common.X, 3*5; got != want {
+               log.Fatalf("before plugin load common.X=%d, want %d", got, want)
+       }
+
+       p, err := plugin.Open("plugin1.so")
+       if err != nil {
+               log.Fatalf("plugin.Open failed: %v", err)
+       }
+
+       const wantX = 3 * 5 * 7
+       if got := common.X; got != wantX {
+               log.Fatalf("after plugin load common.X=%d, want %d", got, wantX)
+       }
+
+       seven, err := p.Lookup("Seven")
+       if err != nil {
+               log.Fatalf(`Lookup("Seven") failed: %v`, err)
+       }
+       if got, want := *seven.(*int), 7; got != want {
+               log.Fatalf("plugin1.Seven=%d, want %d", got, want)
+       }
+
+       readFunc, err := p.Lookup("ReadCommonX")
+       if err != nil {
+               log.Fatalf(`plugin1.Lookup("ReadCommonX") failed: %v`, err)
+       }
+       if got := readFunc.(func() int)(); got != wantX {
+               log.Fatalf("plugin1.ReadCommonX()=%d, want %d", got, wantX)
+       }
+
+       // sub/plugin1.so is a different plugin with the same name as
+       // the already loaded plugin. It also depends on common. Test
+       // that we can load the different plugin, it is actually
+       // different, and that it sees the same common package.
+       subpPath, err := filepath.Abs("sub/plugin1.so")
+       if err != nil {
+               log.Fatalf("filepath.Abs(%q) failed: %v", subpPath, err)
+       }
+       subp, err := plugin.Open(subpPath)
+       if err != nil {
+               log.Fatalf("plugin.Open(%q) failed: %v", subpPath, err)
+       }
+
+       funcVar, err := subp.Lookup("FuncVar")
+       if err != nil {
+               log.Fatalf(`sub/plugin1.Lookup("FuncVar") failed: %v`, err)
+       }
+       called := false
+       *funcVar.(*func()) = func() {
+               called = true
+       }
+
+       readFunc, err = subp.Lookup("ReadCommonX")
+       if err != nil {
+               log.Fatalf(`sub/plugin1.Lookup("ReadCommonX") failed: %v`, err)
+       }
+       if got := readFunc.(func() int)(); got != wantX {
+               log.Fatalf("sub/plugin1.ReadCommonX()=%d, want %d", got, wantX)
+       }
+       if !called {
+               log.Fatal("calling ReadCommonX did not call FuncVar")
+       }
+
+       subf, err := subp.Lookup("F")
+       if err != nil {
+               log.Fatalf(`sub/plugin1.Lookup("F") failed: %v`, err)
+       }
+       if gotf := subf.(func() int)(); gotf != 17 {
+               log.Fatalf(`sub/plugin1.F()=%d, want 17`, gotf)
+       }
+       f, err := p.Lookup("F")
+       if err != nil {
+               log.Fatalf(`plugin1.Lookup("F") failed: %v`, err)
+       }
+       if gotf := f.(func() int)(); gotf != 3 {
+               log.Fatalf(`plugin1.F()=%d, want 17`, gotf)
+       }
+
+       // plugin2 has no exported symbols, only an init function.
+       if _, err := plugin.Open("plugin2.so"); err != nil {
+               log.Fatalf("plugin.Open failed: %v", err)
+       }
+       if got, want := common.X, 2; got != want {
+               log.Fatalf("after loading plugin2, common.X=%d, want %d", got, want)
+       }
+
+       _, err = plugin.Open("plugin-mismatch.so")
+       if err == nil {
+               log.Fatal(`plugin.Open("plugin-mismatch.so"): should have failed`)
+       }
+       if s := err.Error(); !strings.Contains(s, "different version") {
+               log.Fatalf(`plugin.Open("plugin-mismatch.so"): error does not mention "different version": %v`, s)
+       }
+
+       testUnnamed()
+
+       fmt.Println("PASS")
+}
diff --git a/libgo/misc/cgo/testplugin/src/iface/main.go b/libgo/misc/cgo/testplugin/src/iface/main.go
new file mode 100644 (file)
index 0000000..5e7e4d8
--- /dev/null
@@ -0,0 +1,46 @@
+// 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.
+
+package main
+
+import (
+       "iface_i"
+       "log"
+       "plugin"
+)
+
+func main() {
+       a, err := plugin.Open("iface_a.so")
+       if err != nil {
+               log.Fatalf(`plugin.Open("iface_a.so"): %v`, err)
+       }
+       b, err := plugin.Open("iface_b.so")
+       if err != nil {
+               log.Fatalf(`plugin.Open("iface_b.so"): %v`, err)
+       }
+
+       af, err := a.Lookup("F")
+       if err != nil {
+               log.Fatalf(`a.Lookup("F") failed: %v`, err)
+       }
+       bf, err := b.Lookup("F")
+       if err != nil {
+               log.Fatalf(`b.Lookup("F") failed: %v`, err)
+       }
+       if af.(func() interface{})() != bf.(func() interface{})() {
+               panic("empty interfaces not equal")
+       }
+
+       ag, err := a.Lookup("G")
+       if err != nil {
+               log.Fatalf(`a.Lookup("G") failed: %v`, err)
+       }
+       bg, err := b.Lookup("G")
+       if err != nil {
+               log.Fatalf(`b.Lookup("G") failed: %v`, err)
+       }
+       if ag.(func() iface_i.I)() != bg.(func() iface_i.I)() {
+               panic("nonempty interfaces not equal")
+       }
+}
diff --git a/libgo/misc/cgo/testplugin/src/iface_a/a.go b/libgo/misc/cgo/testplugin/src/iface_a/a.go
new file mode 100644 (file)
index 0000000..29d2e27
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+package main
+
+import "iface_i"
+
+//go:noinline
+func F() interface{} {
+       return (*iface_i.T)(nil)
+}
+
+//go:noinline
+func G() iface_i.I {
+       return (*iface_i.T)(nil)
+}
diff --git a/libgo/misc/cgo/testplugin/src/iface_b/b.go b/libgo/misc/cgo/testplugin/src/iface_b/b.go
new file mode 100644 (file)
index 0000000..29d2e27
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+package main
+
+import "iface_i"
+
+//go:noinline
+func F() interface{} {
+       return (*iface_i.T)(nil)
+}
+
+//go:noinline
+func G() iface_i.I {
+       return (*iface_i.T)(nil)
+}
diff --git a/libgo/misc/cgo/testplugin/src/iface_i/i.go b/libgo/misc/cgo/testplugin/src/iface_i/i.go
new file mode 100644 (file)
index 0000000..31c8038
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+package iface_i
+
+type I interface {
+       M()
+}
+
+type T struct {
+}
+
+func (t *T) M() {
+}
+
+// *T implements I
diff --git a/libgo/misc/cgo/testplugin/src/issue18676/dynamodbstreamsevt/definition.go b/libgo/misc/cgo/testplugin/src/issue18676/dynamodbstreamsevt/definition.go
new file mode 100644 (file)
index 0000000..70fd054
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+
+package dynamodbstreamsevt
+
+import "encoding/json"
+
+var foo json.RawMessage
+
+type Event struct{}
+
+func (e *Event) Dummy() {}
diff --git a/libgo/misc/cgo/testplugin/src/issue18676/main.go b/libgo/misc/cgo/testplugin/src/issue18676/main.go
new file mode 100644 (file)
index 0000000..c75409d
--- /dev/null
@@ -0,0 +1,31 @@
+// 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.
+
+// The bug happened like this:
+// 1) The main binary adds an itab for *json.UnsupportedValueError / error
+//    (concrete type / interface type).  This itab goes in hash bucket 0x111.
+// 2) The plugin adds that same itab again.  That makes a cycle in the itab
+//    chain rooted at hash bucket 0x111.
+// 3) The main binary then asks for the itab for *dynamodbstreamsevt.Event /
+//    json.Unmarshaler.  This itab happens to also live in bucket 0x111.
+//    The lookup code goes into an infinite loop searching for this itab.
+// The code is carefully crafted so that the two itabs are both from the
+// same bucket, and so that the second itab doesn't exist in
+// the itab hashmap yet (so the entire linked list must be searched).
+package main
+
+import (
+       "encoding/json"
+       "issue18676/dynamodbstreamsevt"
+       "plugin"
+)
+
+func main() {
+       plugin.Open("plugin.so")
+
+       var x interface{} = (*dynamodbstreamsevt.Event)(nil)
+       if _, ok := x.(json.Unmarshaler); !ok {
+               println("something")
+       }
+}
diff --git a/libgo/misc/cgo/testplugin/src/issue18676/plugin.go b/libgo/misc/cgo/testplugin/src/issue18676/plugin.go
new file mode 100644 (file)
index 0000000..8a3b85a
--- /dev/null
@@ -0,0 +1,11 @@
+// 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.
+
+package main
+
+import "C"
+
+import "issue18676/dynamodbstreamsevt"
+
+func F(evt *dynamodbstreamsevt.Event) {}
diff --git a/libgo/misc/cgo/testplugin/src/plugin1/plugin1.go b/libgo/misc/cgo/testplugin/src/plugin1/plugin1.go
new file mode 100644 (file)
index 0000000..edcef2c
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2016 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.
+
+package main
+
+// // No C code required.
+import "C"
+
+import "common"
+
+func F() int {
+       _ = make([]byte, 1<<21) // trigger stack unwind, Issue #18190.
+       return 3
+}
+
+func ReadCommonX() int {
+       return common.X
+}
+
+var Seven int
+
+func call(fn func()) {
+       fn()
+}
+
+func g() {
+       common.X *= Seven
+}
+
+func init() {
+       Seven = 7
+       call(g)
+}
+
+func main() {
+       panic("plugin1.main called")
+}
diff --git a/libgo/misc/cgo/testplugin/src/plugin2/plugin2.go b/libgo/misc/cgo/testplugin/src/plugin2/plugin2.go
new file mode 100644 (file)
index 0000000..9c507fc
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2016 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.
+
+package main
+
+//#include <errno.h>
+//#include <string.h>
+import "C"
+
+// #include
+// void cfunc() {} // uses cgo_topofstack
+
+import (
+       "common"
+       "strings"
+)
+
+func init() {
+       _ = strings.NewReplacer() // trigger stack unwind, Issue #18190.
+       C.strerror(C.EIO)         // uses cgo_topofstack
+       common.X = 2
+}
+
+func main() {
+       panic("plugin1.main called")
+}
diff --git a/libgo/misc/cgo/testplugin/src/sub/plugin1/plugin1.go b/libgo/misc/cgo/testplugin/src/sub/plugin1/plugin1.go
new file mode 100644 (file)
index 0000000..cf9000c
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2016 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.
+
+package main
+
+// // No C code required.
+import "C"
+
+import "common"
+
+func F() int { return 17 }
+
+var FuncVar = func() {}
+
+func ReadCommonX() int {
+       FuncVar()
+       return common.X
+}
+
+func main() {
+       panic("plugin1.main called")
+}
diff --git a/libgo/misc/cgo/testplugin/test.bash b/libgo/misc/cgo/testplugin/test.bash
new file mode 100644 (file)
index 0000000..ab7430a
--- /dev/null
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+# Copyright 2016 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.
+
+set -e
+
+if [ ! -f src/host/host.go ]; then
+       cwd=$(pwd)
+       echo "misc/cgo/testplugin/test.bash is running in $cwd" 1>&2
+       exit 1
+fi
+
+goos=$(go env GOOS)
+goarch=$(go env GOARCH)
+
+function cleanup() {
+       rm -f plugin*.so unnamed*.so iface*.so
+       rm -rf host pkg sub iface issue18676
+}
+trap cleanup EXIT
+
+rm -rf pkg sub
+mkdir sub
+
+GOPATH=$(pwd) go build -buildmode=plugin plugin1
+GOPATH=$(pwd) go build -buildmode=plugin plugin2
+GOPATH=$(pwd)/altpath go build -buildmode=plugin plugin-mismatch
+GOPATH=$(pwd) go build -buildmode=plugin -o=sub/plugin1.so sub/plugin1
+GOPATH=$(pwd) go build -buildmode=plugin unnamed1.go
+GOPATH=$(pwd) go build -buildmode=plugin unnamed2.go
+GOPATH=$(pwd) go build host
+
+LD_LIBRARY_PATH=$(pwd) ./host
+
+# Test that types and itabs get properly uniqified.
+GOPATH=$(pwd) go build -buildmode=plugin iface_a
+GOPATH=$(pwd) go build -buildmode=plugin iface_b
+GOPATH=$(pwd) go build iface
+LD_LIBRARY_PATH=$(pwd) ./iface
+
+# Test for issue 18676 - make sure we don't add the same itab twice.
+# The buggy code hangs forever, so use a timeout to check for that.
+GOPATH=$(pwd) go build -buildmode=plugin -o plugin.so src/issue18676/plugin.go
+GOPATH=$(pwd) go build -o issue18676 src/issue18676/main.go
+timeout 10s ./issue18676
diff --git a/libgo/misc/cgo/testplugin/unnamed1.go b/libgo/misc/cgo/testplugin/unnamed1.go
new file mode 100644 (file)
index 0000000..102edaf
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2016 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.
+
+package main
+
+// // No C code required.
+import "C"
+
+func FuncInt() int { return 1 }
+
+func main() {}
diff --git a/libgo/misc/cgo/testplugin/unnamed2.go b/libgo/misc/cgo/testplugin/unnamed2.go
new file mode 100644 (file)
index 0000000..55070d5
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2016 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.
+
+package main
+
+// // No C code required.
+import "C"
+
+func FuncInt() int { return 2 }
+
+func main() {}
diff --git a/libgo/misc/cgo/testsanitizers/msan.go b/libgo/misc/cgo/testsanitizers/msan.go
new file mode 100644 (file)
index 0000000..7915fa8
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2015 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.
+
+package main
+
+/*
+#include <stdint.h>
+
+void f(int32_t *p, int n) {
+  int i;
+
+  for (i = 0; i < n; i++) {
+    p[i] = (int32_t)i;
+  }
+}
+*/
+import "C"
+
+import (
+       "fmt"
+       "os"
+       "unsafe"
+)
+
+func main() {
+       a := make([]int32, 10)
+       C.f((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+       for i, v := range a {
+               if i != int(v) {
+                       fmt.Println("bad %d: %v\n", i, a)
+                       os.Exit(1)
+               }
+       }
+}
diff --git a/libgo/misc/cgo/testsanitizers/msan2.go b/libgo/misc/cgo/testsanitizers/msan2.go
new file mode 100644 (file)
index 0000000..6690cb0
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2015 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.
+
+package main
+
+/*
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+void f(int32_t *p, int n) {
+  int32_t * volatile q = (int32_t *)malloc(sizeof(int32_t) * n);
+  memcpy(p, q, n * sizeof(*p));
+  free(q);
+}
+
+void g(int32_t *p, int n) {
+  if (p[4] != 1) {
+    abort();
+  }
+}
+*/
+import "C"
+
+import (
+       "unsafe"
+)
+
+func main() {
+       a := make([]int32, 10)
+       C.f((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+       a[4] = 1
+       C.g((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+}
diff --git a/libgo/misc/cgo/testsanitizers/msan3.go b/libgo/misc/cgo/testsanitizers/msan3.go
new file mode 100644 (file)
index 0000000..61a9c29
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2015 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.
+
+package main
+
+/*
+extern int *GoFn(int *);
+
+// Yes, you can have definitions if you use //export, as long as they are weak.
+int f(void) __attribute__ ((weak));
+
+int f() {
+  int i;
+  int *p = GoFn(&i);
+  if (*p != 12345)
+    return 0;
+  return 1;
+}
+*/
+import "C"
+
+//export GoFn
+func GoFn(p *C.int) *C.int {
+       *p = C.int(12345)
+       return p
+}
+
+func main() {
+       if r := C.f(); r != 1 {
+               panic(r)
+       }
+}
diff --git a/libgo/misc/cgo/testsanitizers/msan4.go b/libgo/misc/cgo/testsanitizers/msan4.go
new file mode 100644 (file)
index 0000000..6c91ff5
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2015 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.
+
+package main
+
+// The memory profiler can call copy from a slice on the system stack,
+// which msan used to think meant a reference to uninitialized memory.
+
+/*
+#include <time.h>
+#include <unistd.h>
+
+extern void Nop(char*);
+
+// Use weak as a hack to permit defining a function even though we use export.
+void poison() __attribute__ ((weak));
+
+// Poison the stack.
+void poison() {
+       char a[1024];
+       Nop(&a[0]);
+}
+
+*/
+import "C"
+
+import (
+       "runtime"
+)
+
+func main() {
+       runtime.MemProfileRate = 1
+       start(100)
+}
+
+func start(i int) {
+       if i == 0 {
+               return
+       }
+       C.poison()
+       // Tie up a thread.
+       // We won't actually wait for this sleep to complete.
+       go func() { C.sleep(1) }()
+       start(i - 1)
+}
+
+//export Nop
+func Nop(*C.char) {
+}
diff --git a/libgo/misc/cgo/testsanitizers/msan5.go b/libgo/misc/cgo/testsanitizers/msan5.go
new file mode 100644 (file)
index 0000000..f1479eb
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright 2016 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.
+
+package main
+
+// Using reflect to set a value was not seen by msan.
+
+/*
+#include <stdlib.h>
+
+extern void Go1(int*);
+extern void Go2(char*);
+
+// Use weak as a hack to permit defining a function even though we use export.
+void C1() __attribute__ ((weak));
+void C2() __attribute__ ((weak));
+
+void C1() {
+       int i;
+       Go1(&i);
+       if (i != 42) {
+               abort();
+       }
+}
+
+void C2() {
+       char a[2];
+       a[1] = 42;
+       Go2(a);
+       if (a[0] != 42) {
+               abort();
+       }
+}
+*/
+import "C"
+
+import (
+       "reflect"
+       "unsafe"
+)
+
+//export Go1
+func Go1(p *C.int) {
+       reflect.ValueOf(p).Elem().Set(reflect.ValueOf(C.int(42)))
+}
+
+//export Go2
+func Go2(p *C.char) {
+       a := (*[2]byte)(unsafe.Pointer(p))
+       reflect.Copy(reflect.ValueOf(a[:1]), reflect.ValueOf(a[1:]))
+}
+
+func main() {
+       C.C1()
+       C.C2()
+}
diff --git a/libgo/misc/cgo/testsanitizers/msan_fail.go b/libgo/misc/cgo/testsanitizers/msan_fail.go
new file mode 100644 (file)
index 0000000..4c8dab3
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2015 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.
+
+package main
+
+/*
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+void f(int32_t *p, int n) {
+  int32_t * volatile q = (int32_t *)malloc(sizeof(int32_t) * n);
+  memcpy(p, q, n * sizeof(*p));
+  free(q);
+}
+
+void g(int32_t *p, int n) {
+  if (p[4] != 1) {
+    // We shouldn't get here; msan should stop us first.
+    exit(0);
+  }
+}
+*/
+import "C"
+
+import (
+       "unsafe"
+)
+
+func main() {
+       a := make([]int32, 10)
+       C.f((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+       a[3] = 1
+       C.g((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+}
diff --git a/libgo/misc/cgo/testsanitizers/msan_shared.go b/libgo/misc/cgo/testsanitizers/msan_shared.go
new file mode 100644 (file)
index 0000000..966947c
--- /dev/null
@@ -0,0 +1,12 @@
+// 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.
+
+// This program segfaulted during libpreinit when built with -msan:
+// http://golang.org/issue/18707
+
+package main
+
+import "C"
+
+func main() {}
diff --git a/libgo/misc/cgo/testsanitizers/test.bash b/libgo/misc/cgo/testsanitizers/test.bash
new file mode 100644 (file)
index 0000000..4da8502
--- /dev/null
@@ -0,0 +1,204 @@
+#!/usr/bin/env bash
+# Copyright 2015 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.
+
+# This directory is intended to test the use of Go with sanitizers
+# like msan, asan, etc.  See https://github.com/google/sanitizers .
+
+set -e
+
+# The sanitizers were originally developed with clang, so prefer it.
+CC=cc
+if test -x "$(type -p clang)"; then
+  CC=clang
+fi
+export CC
+
+if [ "$(sysctl -n vm.overcommit_memory)" = 2 ]; then
+  echo "skipping msan/tsan tests: vm.overcommit_memory=2" >&2
+  exit 0
+fi
+
+msan=yes
+
+TMPDIR=${TMPDIR:-/tmp}
+echo 'int main() { return 0; }' > ${TMPDIR}/testsanitizers$$.c
+if $CC -fsanitize=memory -o ${TMPDIR}/testsanitizers$$ ${TMPDIR}/testsanitizers$$.c 2>&1 | grep "unrecognized" >& /dev/null; then
+  echo "skipping msan tests: $CC -fsanitize=memory not supported"
+  msan=no
+elif ! test -x ${TMPDIR}/testsanitizers$$; then
+  echo "skipping msan tests: $CC -fsanitize-memory did not generate an executable"
+  msan=no
+elif ! ${TMPDIR}/testsanitizers$$ >/dev/null 2>&1; then
+  echo "skipping msan tests: $CC -fsanitize-memory generates broken executable"
+  msan=no
+fi
+rm -f ${TMPDIR}/testsanitizers$$.*
+
+tsan=yes
+
+# The memory and thread sanitizers in versions of clang before 3.6
+# don't work with Go.
+if test "$msan" = "yes" && $CC --version | grep clang >& /dev/null; then
+  ver=$($CC --version | sed -e 's/.* version \([0-9.-]*\).*/\1/')
+  major=$(echo $ver | sed -e 's/\([0-9]*\).*/\1/')
+  minor=$(echo $ver | sed -e 's/[0-9]*\.\([0-9]*\).*/\1/')
+  if test "$major" -lt 3 || test "$major" -eq 3 -a "$minor" -lt 6; then
+    echo "skipping msan/tsan tests: clang version $major.$minor (older than 3.6)"
+    msan=no
+    tsan=no
+  fi
+
+  # Clang before 3.8 does not work with Linux at or after 4.1.
+  # golang.org/issue/12898.
+  if test "$msan" = "yes" -a "$major" -lt 3 || test "$major" -eq 3 -a "$minor" -lt 8; then
+    if test "$(uname)" = Linux; then
+      linuxver=$(uname -r)
+      linuxmajor=$(echo $linuxver | sed -e 's/\([0-9]*\).*/\1/')
+      linuxminor=$(echo $linuxver | sed -e 's/[0-9]*\.\([0-9]*\).*/\1/')
+      if test "$linuxmajor" -gt 4 || test "$linuxmajor" -eq 4 -a "$linuxminor" -ge 1; then
+        echo "skipping msan/tsan tests: clang version $major.$minor (older than 3.8) incompatible with linux version $linuxmajor.$linuxminor (4.1 or newer)"
+       msan=no
+       tsan=no
+      fi
+    fi
+  fi
+fi
+
+status=0
+
+testmsanshared() {
+  goos=$(go env GOOS)
+  suffix="-installsuffix testsanitizers"
+  libext="so"
+  if [ "$goos" == "darwin" ]; then
+         libext="dylib"
+  fi
+  go build -msan -buildmode=c-shared $suffix -o ${TMPDIR}/libmsanshared.$libext msan_shared.go
+
+       echo 'int main() { return 0; }' > ${TMPDIR}/testmsanshared.c
+  $CC $(go env GOGCCFLAGS) -fsanitize=memory -o ${TMPDIR}/testmsanshared ${TMPDIR}/testmsanshared.c ${TMPDIR}/libmsanshared.$libext
+
+  if ! LD_LIBRARY_PATH=. ${TMPDIR}/testmsanshared; then
+    echo "FAIL: msan_shared"
+    status=1
+  fi
+  rm -f ${TMPDIR}/{testmsanshared,testmsanshared.c,libmsanshared.$libext}
+}
+
+if test "$msan" = "yes"; then
+    if ! go build -msan std; then
+       echo "FAIL: build -msan std"
+       status=1
+    fi
+
+    if ! go run -msan msan.go; then
+       echo "FAIL: msan"
+       status=1
+    fi
+
+    if ! CGO_LDFLAGS="-fsanitize=memory" CGO_CPPFLAGS="-fsanitize=memory" go run -msan -a msan2.go; then
+       echo "FAIL: msan2 with -fsanitize=memory"
+       status=1
+    fi
+
+    if ! go run -msan -a msan2.go; then
+       echo "FAIL: msan2"
+       status=1
+    fi
+
+    if ! go run -msan msan3.go; then
+       echo "FAIL: msan3"
+       status=1
+    fi
+
+    if ! go run -msan msan4.go; then
+       echo "FAIL: msan4"
+       status=1
+    fi
+
+    if ! go run -msan msan5.go; then
+       echo "FAIL: msan5"
+       status=1
+    fi
+
+    if go run -msan msan_fail.go 2>/dev/null; then
+       echo "FAIL: msan_fail"
+       status=1
+    fi
+
+    testmsanshared
+fi
+
+if test "$tsan" = "yes"; then
+    echo 'int main() { return 0; }' > ${TMPDIR}/testsanitizers$$.c
+    ok=yes
+    if ! $CC -fsanitize=thread ${TMPDIR}/testsanitizers$$.c -o ${TMPDIR}/testsanitizers$$ &> ${TMPDIR}/testsanitizers$$.err; then
+       ok=no
+    fi
+     if grep "unrecognized" ${TMPDIR}/testsanitizers$$.err >& /dev/null; then
+       echo "skipping tsan tests: -fsanitize=thread not supported"
+       tsan=no
+     elif test "$ok" != "yes"; then
+        cat ${TMPDIR}/testsanitizers$$.err
+        echo "skipping tsan tests: -fsanitizer=thread build failed"
+        tsan=no
+     fi
+     rm -f ${TMPDIR}/testsanitizers$$*
+fi
+
+# Run a TSAN test.
+# $1 test name
+# $2 environment variables
+# $3 go run args
+testtsan() {
+    err=${TMPDIR}/tsanerr$$.out
+    if ! env $2 go run $3 $1 2>$err; then
+       cat $err
+       echo "FAIL: $1"
+       status=1
+    elif grep -i warning $err >/dev/null 2>&1; then
+       cat $err
+       echo "FAIL: $1"
+       status=1
+    fi
+    rm -f $err
+}
+
+if test "$tsan" = "yes"; then
+    testtsan tsan.go
+    testtsan tsan2.go
+    testtsan tsan3.go
+    testtsan tsan4.go
+    testtsan tsan8.go
+    testtsan tsan9.go
+
+    # These tests are only reliable using clang or GCC version 7 or later.
+    # Otherwise runtime/cgo/libcgo.h can't tell whether TSAN is in use.
+    ok=false
+    if ${CC} --version | grep clang >/dev/null 2>&1; then
+       ok=true
+    else
+       ver=$($CC -dumpversion)
+       major=$(echo $ver | sed -e 's/\([0-9]*\).*/\1/')
+       if test "$major" -lt 7; then
+           echo "skipping remaining TSAN tests: GCC version $major (older than 7)"
+       else
+           ok=true
+       fi
+    fi
+
+    if test "$ok" = "true"; then
+       # This test requires rebuilding os/user with -fsanitize=thread.
+       testtsan tsan5.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
+
+       # This test requires rebuilding runtime/cgo with -fsanitize=thread.
+       testtsan tsan6.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
+
+       # This test requires rebuilding runtime/cgo with -fsanitize=thread.
+       testtsan tsan7.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
+    fi
+fi
+
+exit $status
diff --git a/libgo/misc/cgo/testsanitizers/tsan.go b/libgo/misc/cgo/testsanitizers/tsan.go
new file mode 100644 (file)
index 0000000..6c377a7
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2015 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.
+
+package main
+
+// This program produced false race reports when run under the C/C++
+// ThreadSanitizer, as it did not understand the synchronization in
+// the Go code.
+
+/*
+#cgo CFLAGS: -fsanitize=thread
+#cgo LDFLAGS: -fsanitize=thread
+
+int val;
+
+int getVal() {
+       return val;
+}
+
+void setVal(int i) {
+       val = i;
+}
+*/
+import "C"
+
+import (
+       "runtime"
+)
+
+func main() {
+       runtime.LockOSThread()
+       C.setVal(1)
+       c := make(chan bool)
+       go func() {
+               runtime.LockOSThread()
+               C.setVal(2)
+               c <- true
+       }()
+       <-c
+       if v := C.getVal(); v != 2 {
+               panic(v)
+       }
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan2.go b/libgo/misc/cgo/testsanitizers/tsan2.go
new file mode 100644 (file)
index 0000000..5018a19
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright 2015 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.
+
+package main
+
+// This program produced false race reports when run under the C/C++
+// ThreadSanitizer, as it did not understand the synchronization in
+// the Go code.
+
+/*
+#cgo CFLAGS: -fsanitize=thread
+#cgo LDFLAGS: -fsanitize=thread
+
+extern void GoRun(void);
+
+// Yes, you can have definitions if you use //export, as long as they are weak.
+
+int val __attribute__ ((weak));
+
+int run(void) __attribute__ ((weak));
+
+int run() {
+       val = 1;
+       GoRun();
+       return val;
+}
+
+void setVal(int) __attribute__ ((weak));
+
+void setVal(int i) {
+       val = i;
+}
+*/
+import "C"
+
+import "runtime"
+
+//export GoRun
+func GoRun() {
+       runtime.LockOSThread()
+       c := make(chan bool)
+       go func() {
+               runtime.LockOSThread()
+               C.setVal(2)
+               c <- true
+       }()
+       <-c
+}
+
+func main() {
+       if v := C.run(); v != 2 {
+               panic(v)
+       }
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan3.go b/libgo/misc/cgo/testsanitizers/tsan3.go
new file mode 100644 (file)
index 0000000..87f6c80
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2016 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.
+
+package main
+
+// The stubs for the C functions read and write the same slot on the
+// g0 stack when copying arguments in and out.
+
+/*
+#cgo CFLAGS: -fsanitize=thread
+#cgo LDFLAGS: -fsanitize=thread
+
+int Func1() {
+       return 0;
+}
+
+void Func2(int x) {
+       (void)x;
+}
+*/
+import "C"
+
+func main() {
+       const N = 10000
+       done := make(chan bool, N)
+       for i := 0; i < N; i++ {
+               go func() {
+                       C.Func1()
+                       done <- true
+               }()
+               go func() {
+                       C.Func2(0)
+                       done <- true
+               }()
+       }
+       for i := 0; i < 2*N; i++ {
+               <-done
+       }
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan4.go b/libgo/misc/cgo/testsanitizers/tsan4.go
new file mode 100644 (file)
index 0000000..f0c76d8
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2016 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.
+
+package main
+
+// Check that calls to C.malloc/C.free do not trigger TSAN false
+// positive reports.
+
+// #cgo CFLAGS: -fsanitize=thread
+// #cgo LDFLAGS: -fsanitize=thread
+// #include <stdlib.h>
+import "C"
+
+import (
+       "runtime"
+       "sync"
+)
+
+func main() {
+       var wg sync.WaitGroup
+       for i := 0; i < 10; i++ {
+               wg.Add(1)
+               go func() {
+                       defer wg.Done()
+                       for i := 0; i < 100; i++ {
+                               p := C.malloc(C.size_t(i * 10))
+                               runtime.Gosched()
+                               C.free(p)
+                       }
+               }()
+       }
+       wg.Wait()
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan5.go b/libgo/misc/cgo/testsanitizers/tsan5.go
new file mode 100644 (file)
index 0000000..1214a77
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright 2016 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.
+
+package main
+
+// Check that calls to C.malloc/C.free do not collide with the calls
+// made by the os/user package.
+
+// #cgo CFLAGS: -fsanitize=thread
+// #cgo LDFLAGS: -fsanitize=thread
+// #include <stdlib.h>
+import "C"
+
+import (
+       "fmt"
+       "os"
+       "os/user"
+       "runtime"
+       "sync"
+)
+
+func main() {
+       u, err := user.Current()
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               // Let the test pass.
+               os.Exit(0)
+       }
+
+       var wg sync.WaitGroup
+       for i := 0; i < 20; i++ {
+               wg.Add(2)
+               go func() {
+                       defer wg.Done()
+                       for i := 0; i < 1000; i++ {
+                               user.Lookup(u.Username)
+                               runtime.Gosched()
+                       }
+               }()
+               go func() {
+                       defer wg.Done()
+                       for i := 0; i < 1000; i++ {
+                               p := C.malloc(C.size_t(len(u.Username) + 1))
+                               runtime.Gosched()
+                               C.free(p)
+                       }
+               }()
+       }
+       wg.Wait()
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan6.go b/libgo/misc/cgo/testsanitizers/tsan6.go
new file mode 100644 (file)
index 0000000..c96f08d
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2016 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.
+
+package main
+
+// Check that writes to Go allocated memory, with Go synchronization,
+// do not look like a race.
+
+/*
+#cgo CFLAGS: -fsanitize=thread
+#cgo LDFLAGS: -fsanitize=thread
+
+void f(char *p) {
+       *p = 1;
+}
+*/
+import "C"
+
+import (
+       "runtime"
+       "sync"
+)
+
+func main() {
+       var wg sync.WaitGroup
+       var mu sync.Mutex
+       c := make(chan []C.char, 100)
+       for i := 0; i < 10; i++ {
+               wg.Add(2)
+               go func() {
+                       defer wg.Done()
+                       for i := 0; i < 100; i++ {
+                               c <- make([]C.char, 4096)
+                               runtime.Gosched()
+                       }
+               }()
+               go func() {
+                       defer wg.Done()
+                       for i := 0; i < 100; i++ {
+                               p := &(<-c)[0]
+                               mu.Lock()
+                               C.f(p)
+                               mu.Unlock()
+                       }
+               }()
+       }
+       wg.Wait()
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan7.go b/libgo/misc/cgo/testsanitizers/tsan7.go
new file mode 100644 (file)
index 0000000..2fb9e45
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2016 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.
+
+package main
+
+// Setting an environment variable in a cgo program changes the C
+// environment. Test that this does not confuse the race detector.
+
+/*
+#cgo CFLAGS: -fsanitize=thread
+#cgo LDFLAGS: -fsanitize=thread
+*/
+import "C"
+
+import (
+       "fmt"
+       "os"
+       "sync"
+       "time"
+)
+
+func main() {
+       var wg sync.WaitGroup
+       var mu sync.Mutex
+       f := func() {
+               defer wg.Done()
+               for i := 0; i < 100; i++ {
+                       time.Sleep(time.Microsecond)
+                       mu.Lock()
+                       s := fmt.Sprint(i)
+                       os.Setenv("TSAN_TEST"+s, s)
+                       mu.Unlock()
+               }
+       }
+       wg.Add(2)
+       go f()
+       go f()
+       wg.Wait()
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan8.go b/libgo/misc/cgo/testsanitizers/tsan8.go
new file mode 100644 (file)
index 0000000..88d82a6
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright 2016 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.
+
+package main
+
+// This program failed when run under the C/C++ ThreadSanitizer.  The TSAN
+// sigaction function interceptor returned SIG_DFL instead of the Go runtime's
+// handler in registerSegvForwarder.
+
+/*
+#cgo CFLAGS: -fsanitize=thread
+#cgo LDFLAGS: -fsanitize=thread
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct sigaction prev_sa;
+
+void forwardSignal(int signo, siginfo_t *info, void *context) {
+       // One of sa_sigaction and/or sa_handler
+       if ((prev_sa.sa_flags&SA_SIGINFO) != 0) {
+               prev_sa.sa_sigaction(signo, info, context);
+               return;
+       }
+       if (prev_sa.sa_handler != SIG_IGN && prev_sa.sa_handler != SIG_DFL) {
+               prev_sa.sa_handler(signo);
+               return;
+       }
+
+       fprintf(stderr, "No Go handler to forward to!\n");
+       abort();
+}
+
+void registerSegvFowarder() {
+       struct sigaction sa;
+       memset(&sa, 0, sizeof(sa));
+       sigemptyset(&sa.sa_mask);
+       sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
+       sa.sa_sigaction = forwardSignal;
+
+       if (sigaction(SIGSEGV, &sa, &prev_sa) != 0) {
+               perror("failed to register SEGV forwarder");
+               exit(EXIT_FAILURE);
+       }
+}
+*/
+import "C"
+
+func main() {
+       C.registerSegvFowarder()
+
+       defer func() {
+               recover()
+       }()
+       var nilp *int
+       *nilp = 42
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan9.go b/libgo/misc/cgo/testsanitizers/tsan9.go
new file mode 100644 (file)
index 0000000..f166d8b
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright 2016 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.
+
+package main
+
+// This program failed when run under the C/C++ ThreadSanitizer. The
+// TSAN library was not keeping track of whether signals should be
+// delivered on the alternate signal stack, and the Go signal handler
+// was not preserving callee-saved registers from C callers.
+
+/*
+#cgo CFLAGS: -g -fsanitize=thread
+#cgo LDFLAGS: -g -fsanitize=thread
+
+#include <stdlib.h>
+#include <sys/time.h>
+
+void spin() {
+       size_t n;
+       struct timeval tvstart, tvnow;
+       int diff;
+       void *prev = NULL, *cur;
+
+       gettimeofday(&tvstart, NULL);
+       for (n = 0; n < 1<<20; n++) {
+               cur = malloc(n);
+               free(prev);
+               prev = cur;
+
+               gettimeofday(&tvnow, NULL);
+               diff = (tvnow.tv_sec - tvstart.tv_sec) * 1000 * 1000 + (tvnow.tv_usec - tvstart.tv_usec);
+
+               // Profile frequency is 100Hz so we should definitely
+               // get a signal in 50 milliseconds.
+               if (diff > 50 * 1000) {
+                       break;
+               }
+       }
+
+       free(prev);
+}
+*/
+import "C"
+
+import (
+       "io/ioutil"
+       "runtime/pprof"
+       "time"
+)
+
+func goSpin() {
+       start := time.Now()
+       for n := 0; n < 1<<20; n++ {
+               _ = make([]byte, n)
+               if time.Since(start) > 50*time.Millisecond {
+                       break
+               }
+       }
+}
+
+func main() {
+       pprof.StartCPUProfile(ioutil.Discard)
+       go C.spin()
+       goSpin()
+       pprof.StopCPUProfile()
+}
diff --git a/libgo/misc/cgo/testshared/shared_test.go b/libgo/misc/cgo/testshared/shared_test.go
new file mode 100644 (file)
index 0000000..f0766e5
--- /dev/null
@@ -0,0 +1,828 @@
+// Copyright 2015 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.
+
+package shared_test
+
+import (
+       "bufio"
+       "bytes"
+       "debug/elf"
+       "encoding/binary"
+       "errors"
+       "flag"
+       "fmt"
+       "go/build"
+       "io"
+       "io/ioutil"
+       "log"
+       "math/rand"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "regexp"
+       "runtime"
+       "strings"
+       "testing"
+       "time"
+)
+
+var gopathInstallDir, gorootInstallDir, suffix string
+
+// This is the smallest set of packages we can link into a shared
+// library (runtime/cgo is built implicitly).
+var minpkgs = []string{"runtime", "sync/atomic"}
+var soname = "libruntime,sync-atomic.so"
+
+// run runs a command and calls t.Errorf if it fails.
+func run(t *testing.T, msg string, args ...string) {
+       c := exec.Command(args[0], args[1:]...)
+       if output, err := c.CombinedOutput(); err != nil {
+               t.Errorf("executing %s (%s) failed %s:\n%s", strings.Join(args, " "), msg, err, output)
+       }
+}
+
+// goCmd invokes the go tool with the installsuffix set up by TestMain. It calls
+// t.Fatalf if the command fails.
+func goCmd(t *testing.T, args ...string) {
+       newargs := []string{args[0], "-installsuffix=" + suffix}
+       if testing.Verbose() {
+               newargs = append(newargs, "-v")
+       }
+       newargs = append(newargs, args[1:]...)
+       c := exec.Command("go", newargs...)
+       var output []byte
+       var err error
+       if testing.Verbose() {
+               fmt.Printf("+ go %s\n", strings.Join(newargs, " "))
+               c.Stdout = os.Stdout
+               c.Stderr = os.Stderr
+               err = c.Run()
+       } else {
+               output, err = c.CombinedOutput()
+       }
+       if err != nil {
+               if t != nil {
+                       t.Fatalf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, output)
+               } else {
+                       log.Fatalf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, output)
+               }
+       }
+}
+
+// TestMain calls testMain so that the latter can use defer (TestMain exits with os.Exit).
+func testMain(m *testing.M) (int, error) {
+       // Because go install -buildmode=shared $standard_library_package always
+       // installs into $GOROOT, here are some gymnastics to come up with a unique
+       // installsuffix to use in this test that we can clean up afterwards.
+       myContext := build.Default
+       runtimeP, err := myContext.Import("runtime", ".", build.ImportComment)
+       if err != nil {
+               return 0, fmt.Errorf("import failed: %v", err)
+       }
+       for i := 0; i < 10000; i++ {
+               try := fmt.Sprintf("%s_%d_dynlink", runtimeP.PkgTargetRoot, rand.Int63())
+               err = os.Mkdir(try, 0700)
+               if os.IsExist(err) {
+                       continue
+               }
+               if err == nil {
+                       gorootInstallDir = try
+               }
+               break
+       }
+       if err != nil {
+               return 0, fmt.Errorf("can't create temporary directory: %v", err)
+       }
+       if gorootInstallDir == "" {
+               return 0, errors.New("could not create temporary directory after 10000 tries")
+       }
+       if testing.Verbose() {
+               fmt.Printf("+ mkdir -p %s\n", gorootInstallDir)
+       }
+       defer os.RemoveAll(gorootInstallDir)
+
+       // Some tests need to edit the source in GOPATH, so copy this directory to a
+       // temporary directory and chdir to that.
+       scratchDir, err := ioutil.TempDir("", "testshared")
+       if err != nil {
+               return 0, fmt.Errorf("TempDir failed: %v", err)
+       }
+       if testing.Verbose() {
+               fmt.Printf("+ mkdir -p %s\n", scratchDir)
+       }
+       defer os.RemoveAll(scratchDir)
+       err = filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
+               scratchPath := filepath.Join(scratchDir, path)
+               if info.IsDir() {
+                       if path == "." {
+                               return nil
+                       }
+                       if testing.Verbose() {
+                               fmt.Printf("+ mkdir -p %s\n", scratchPath)
+                       }
+                       return os.Mkdir(scratchPath, info.Mode())
+               } else {
+                       fromBytes, err := ioutil.ReadFile(path)
+                       if err != nil {
+                               return err
+                       }
+                       if testing.Verbose() {
+                               fmt.Printf("+ cp %s %s\n", path, scratchPath)
+                       }
+                       return ioutil.WriteFile(scratchPath, fromBytes, info.Mode())
+               }
+       })
+       if err != nil {
+               return 0, fmt.Errorf("walk failed: %v", err)
+       }
+       os.Setenv("GOPATH", scratchDir)
+       if testing.Verbose() {
+               fmt.Printf("+ export GOPATH=%s\n", scratchDir)
+       }
+       myContext.GOPATH = scratchDir
+       if testing.Verbose() {
+               fmt.Printf("+ cd %s\n", scratchDir)
+       }
+       os.Chdir(scratchDir)
+
+       // All tests depend on runtime being built into a shared library. Because
+       // that takes a few seconds, do it here and have all tests use the version
+       // built here.
+       suffix = strings.Split(filepath.Base(gorootInstallDir), "_")[2]
+       goCmd(nil, append([]string{"install", "-buildmode=shared"}, minpkgs...)...)
+
+       myContext.InstallSuffix = suffix + "_dynlink"
+       depP, err := myContext.Import("depBase", ".", build.ImportComment)
+       if err != nil {
+               return 0, fmt.Errorf("import failed: %v", err)
+       }
+       gopathInstallDir = depP.PkgTargetRoot
+       return m.Run(), nil
+}
+
+func TestMain(m *testing.M) {
+       // Some of the tests install binaries into a custom GOPATH.
+       // That won't work if GOBIN is set.
+       os.Unsetenv("GOBIN")
+
+       flag.Parse()
+       exitCode, err := testMain(m)
+       if err != nil {
+               log.Fatal(err)
+       }
+       os.Exit(exitCode)
+}
+
+// The shared library was built at the expected location.
+func TestSOBuilt(t *testing.T) {
+       _, err := os.Stat(filepath.Join(gorootInstallDir, soname))
+       if err != nil {
+               t.Error(err)
+       }
+}
+
+func hasDynTag(f *elf.File, tag elf.DynTag) bool {
+       ds := f.SectionByType(elf.SHT_DYNAMIC)
+       if ds == nil {
+               return false
+       }
+       d, err := ds.Data()
+       if err != nil {
+               return false
+       }
+       for len(d) > 0 {
+               var t elf.DynTag
+               switch f.Class {
+               case elf.ELFCLASS32:
+                       t = elf.DynTag(f.ByteOrder.Uint32(d[0:4]))
+                       d = d[8:]
+               case elf.ELFCLASS64:
+                       t = elf.DynTag(f.ByteOrder.Uint64(d[0:8]))
+                       d = d[16:]
+               }
+               if t == tag {
+                       return true
+               }
+       }
+       return false
+}
+
+// The shared library does not have relocations against the text segment.
+func TestNoTextrel(t *testing.T) {
+       sopath := filepath.Join(gorootInstallDir, soname)
+       f, err := elf.Open(sopath)
+       if err != nil {
+               t.Fatal("elf.Open failed: ", err)
+       }
+       defer f.Close()
+       if hasDynTag(f, elf.DT_TEXTREL) {
+               t.Errorf("%s has DT_TEXTREL set", soname)
+       }
+}
+
+// The shared library does not contain symbols called ".dup"
+func TestNoDupSymbols(t *testing.T) {
+       sopath := filepath.Join(gorootInstallDir, soname)
+       f, err := elf.Open(sopath)
+       if err != nil {
+               t.Fatal("elf.Open failed: ", err)
+       }
+       defer f.Close()
+       syms, err := f.Symbols()
+       if err != nil {
+               t.Errorf("error reading symbols %v", err)
+               return
+       }
+       for _, s := range syms {
+               if s.Name == ".dup" {
+                       t.Fatalf("%s contains symbol called .dup", sopath)
+               }
+       }
+}
+
+// The install command should have created a "shlibname" file for the
+// listed packages (and runtime/cgo, and math on arm) indicating the
+// name of the shared library containing it.
+func TestShlibnameFiles(t *testing.T) {
+       pkgs := append([]string{}, minpkgs...)
+       pkgs = append(pkgs, "runtime/cgo")
+       if runtime.GOARCH == "arm" {
+               pkgs = append(pkgs, "math")
+       }
+       for _, pkg := range pkgs {
+               shlibnamefile := filepath.Join(gorootInstallDir, pkg+".shlibname")
+               contentsb, err := ioutil.ReadFile(shlibnamefile)
+               if err != nil {
+                       t.Errorf("error reading shlibnamefile for %s: %v", pkg, err)
+                       continue
+               }
+               contents := strings.TrimSpace(string(contentsb))
+               if contents != soname {
+                       t.Errorf("shlibnamefile for %s has wrong contents: %q", pkg, contents)
+               }
+       }
+}
+
+// Is a given offset into the file contained in a loaded segment?
+func isOffsetLoaded(f *elf.File, offset uint64) bool {
+       for _, prog := range f.Progs {
+               if prog.Type == elf.PT_LOAD {
+                       if prog.Off <= offset && offset < prog.Off+prog.Filesz {
+                               return true
+                       }
+               }
+       }
+       return false
+}
+
+func rnd(v int32, r int32) int32 {
+       if r <= 0 {
+               return v
+       }
+       v += r - 1
+       c := v % r
+       if c < 0 {
+               c += r
+       }
+       v -= c
+       return v
+}
+
+func readwithpad(r io.Reader, sz int32) ([]byte, error) {
+       data := make([]byte, rnd(sz, 4))
+       _, err := io.ReadFull(r, data)
+       if err != nil {
+               return nil, err
+       }
+       data = data[:sz]
+       return data, nil
+}
+
+type note struct {
+       name    string
+       tag     int32
+       desc    string
+       section *elf.Section
+}
+
+// Read all notes from f. As ELF section names are not supposed to be special, one
+// looks for a particular note by scanning all SHT_NOTE sections looking for a note
+// with a particular "name" and "tag".
+func readNotes(f *elf.File) ([]*note, error) {
+       var notes []*note
+       for _, sect := range f.Sections {
+               if sect.Type != elf.SHT_NOTE {
+                       continue
+               }
+               r := sect.Open()
+               for {
+                       var namesize, descsize, tag int32
+                       err := binary.Read(r, f.ByteOrder, &namesize)
+                       if err != nil {
+                               if err == io.EOF {
+                                       break
+                               }
+                               return nil, fmt.Errorf("read namesize failed: %v", err)
+                       }
+                       err = binary.Read(r, f.ByteOrder, &descsize)
+                       if err != nil {
+                               return nil, fmt.Errorf("read descsize failed: %v", err)
+                       }
+                       err = binary.Read(r, f.ByteOrder, &tag)
+                       if err != nil {
+                               return nil, fmt.Errorf("read type failed: %v", err)
+                       }
+                       name, err := readwithpad(r, namesize)
+                       if err != nil {
+                               return nil, fmt.Errorf("read name failed: %v", err)
+                       }
+                       desc, err := readwithpad(r, descsize)
+                       if err != nil {
+                               return nil, fmt.Errorf("read desc failed: %v", err)
+                       }
+                       notes = append(notes, &note{name: string(name), tag: tag, desc: string(desc), section: sect})
+               }
+       }
+       return notes, nil
+}
+
+func dynStrings(t *testing.T, path string, flag elf.DynTag) []string {
+       f, err := elf.Open(path)
+       defer f.Close()
+       if err != nil {
+               t.Fatalf("elf.Open(%q) failed: %v", path, err)
+       }
+       dynstrings, err := f.DynString(flag)
+       if err != nil {
+               t.Fatalf("DynString(%s) failed on %s: %v", flag, path, err)
+       }
+       return dynstrings
+}
+
+func AssertIsLinkedToRegexp(t *testing.T, path string, re *regexp.Regexp) {
+       for _, dynstring := range dynStrings(t, path, elf.DT_NEEDED) {
+               if re.MatchString(dynstring) {
+                       return
+               }
+       }
+       t.Errorf("%s is not linked to anything matching %v", path, re)
+}
+
+func AssertIsLinkedTo(t *testing.T, path, lib string) {
+       AssertIsLinkedToRegexp(t, path, regexp.MustCompile(regexp.QuoteMeta(lib)))
+}
+
+func AssertHasRPath(t *testing.T, path, dir string) {
+       for _, tag := range []elf.DynTag{elf.DT_RPATH, elf.DT_RUNPATH} {
+               for _, dynstring := range dynStrings(t, path, tag) {
+                       for _, rpath := range strings.Split(dynstring, ":") {
+                               if filepath.Clean(rpath) == filepath.Clean(dir) {
+                                       return
+                               }
+                       }
+               }
+       }
+       t.Errorf("%s does not have rpath %s", path, dir)
+}
+
+// Build a trivial program that links against the shared runtime and check it runs.
+func TestTrivialExecutable(t *testing.T) {
+       goCmd(t, "install", "-linkshared", "trivial")
+       run(t, "trivial executable", "./bin/trivial")
+       AssertIsLinkedTo(t, "./bin/trivial", soname)
+       AssertHasRPath(t, "./bin/trivial", gorootInstallDir)
+}
+
+// Build a trivial program in PIE mode that links against the shared runtime and check it runs.
+func TestTrivialExecutablePIE(t *testing.T) {
+       goCmd(t, "build", "-buildmode=pie", "-o", "trivial.pie", "-linkshared", "trivial")
+       run(t, "trivial executable", "./trivial.pie")
+       AssertIsLinkedTo(t, "./trivial.pie", soname)
+       AssertHasRPath(t, "./trivial.pie", gorootInstallDir)
+}
+
+// Build an executable that uses cgo linked against the shared runtime and check it
+// runs.
+func TestCgoExecutable(t *testing.T) {
+       goCmd(t, "install", "-linkshared", "execgo")
+       run(t, "cgo executable", "./bin/execgo")
+}
+
+func checkPIE(t *testing.T, name string) {
+       f, err := elf.Open(name)
+       if err != nil {
+               t.Fatal("elf.Open failed: ", err)
+       }
+       defer f.Close()
+       if f.Type != elf.ET_DYN {
+               t.Errorf("%s has type %v, want ET_DYN", name, f.Type)
+       }
+       if hasDynTag(f, elf.DT_TEXTREL) {
+               t.Errorf("%s has DT_TEXTREL set", name)
+       }
+}
+
+func TestTrivialPIE(t *testing.T) {
+       name := "trivial_pie"
+       goCmd(t, "build", "-buildmode=pie", "-o="+name, "trivial")
+       defer os.Remove(name)
+       run(t, name, "./"+name)
+       checkPIE(t, name)
+}
+
+func TestCgoPIE(t *testing.T) {
+       name := "cgo_pie"
+       goCmd(t, "build", "-buildmode=pie", "-o="+name, "execgo")
+       defer os.Remove(name)
+       run(t, name, "./"+name)
+       checkPIE(t, name)
+}
+
+// Build a GOPATH package into a shared library that links against the goroot runtime
+// and an executable that links against both.
+func TestGopathShlib(t *testing.T) {
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
+       AssertIsLinkedTo(t, filepath.Join(gopathInstallDir, "libdepBase.so"), soname)
+       goCmd(t, "install", "-linkshared", "exe")
+       AssertIsLinkedTo(t, "./bin/exe", soname)
+       AssertIsLinkedTo(t, "./bin/exe", "libdepBase.so")
+       AssertHasRPath(t, "./bin/exe", gorootInstallDir)
+       AssertHasRPath(t, "./bin/exe", gopathInstallDir)
+       // And check it runs.
+       run(t, "executable linked to GOPATH library", "./bin/exe")
+}
+
+// The shared library contains a note listing the packages it contains in a section
+// that is not mapped into memory.
+func testPkgListNote(t *testing.T, f *elf.File, note *note) {
+       if note.section.Flags != 0 {
+               t.Errorf("package list section has flags %v", note.section.Flags)
+       }
+       if isOffsetLoaded(f, note.section.Offset) {
+               t.Errorf("package list section contained in PT_LOAD segment")
+       }
+       if note.desc != "depBase\n" {
+               t.Errorf("incorrect package list %q", note.desc)
+       }
+}
+
+// The shared library contains a note containing the ABI hash that is mapped into
+// memory and there is a local symbol called go.link.abihashbytes that points 16
+// bytes into it.
+func testABIHashNote(t *testing.T, f *elf.File, note *note) {
+       if note.section.Flags != elf.SHF_ALLOC {
+               t.Errorf("abi hash section has flags %v", note.section.Flags)
+       }
+       if !isOffsetLoaded(f, note.section.Offset) {
+               t.Errorf("abihash section not contained in PT_LOAD segment")
+       }
+       var hashbytes elf.Symbol
+       symbols, err := f.Symbols()
+       if err != nil {
+               t.Errorf("error reading symbols %v", err)
+               return
+       }
+       for _, sym := range symbols {
+               if sym.Name == "go.link.abihashbytes" {
+                       hashbytes = sym
+               }
+       }
+       if hashbytes.Name == "" {
+               t.Errorf("no symbol called go.link.abihashbytes")
+               return
+       }
+       if elf.ST_BIND(hashbytes.Info) != elf.STB_LOCAL {
+               t.Errorf("%s has incorrect binding %v", hashbytes.Name, elf.ST_BIND(hashbytes.Info))
+       }
+       if f.Sections[hashbytes.Section] != note.section {
+               t.Errorf("%s has incorrect section %v", hashbytes.Name, f.Sections[hashbytes.Section].Name)
+       }
+       if hashbytes.Value-note.section.Addr != 16 {
+               t.Errorf("%s has incorrect offset into section %d", hashbytes.Name, hashbytes.Value-note.section.Addr)
+       }
+}
+
+// A Go shared library contains a note indicating which other Go shared libraries it
+// was linked against in an unmapped section.
+func testDepsNote(t *testing.T, f *elf.File, note *note) {
+       if note.section.Flags != 0 {
+               t.Errorf("package list section has flags %v", note.section.Flags)
+       }
+       if isOffsetLoaded(f, note.section.Offset) {
+               t.Errorf("package list section contained in PT_LOAD segment")
+       }
+       // libdepBase.so just links against the lib containing the runtime.
+       if note.desc != soname {
+               t.Errorf("incorrect dependency list %q", note.desc)
+       }
+}
+
+// The shared library contains notes with defined contents; see above.
+func TestNotes(t *testing.T) {
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
+       f, err := elf.Open(filepath.Join(gopathInstallDir, "libdepBase.so"))
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer f.Close()
+       notes, err := readNotes(f)
+       if err != nil {
+               t.Fatal(err)
+       }
+       pkgListNoteFound := false
+       abiHashNoteFound := false
+       depsNoteFound := false
+       for _, note := range notes {
+               if note.name != "Go\x00\x00" {
+                       continue
+               }
+               switch note.tag {
+               case 1: // ELF_NOTE_GOPKGLIST_TAG
+                       if pkgListNoteFound {
+                               t.Error("multiple package list notes")
+                       }
+                       testPkgListNote(t, f, note)
+                       pkgListNoteFound = true
+               case 2: // ELF_NOTE_GOABIHASH_TAG
+                       if abiHashNoteFound {
+                               t.Error("multiple abi hash notes")
+                       }
+                       testABIHashNote(t, f, note)
+                       abiHashNoteFound = true
+               case 3: // ELF_NOTE_GODEPS_TAG
+                       if depsNoteFound {
+                               t.Error("multiple abi hash notes")
+                       }
+                       testDepsNote(t, f, note)
+                       depsNoteFound = true
+               }
+       }
+       if !pkgListNoteFound {
+               t.Error("package list note not found")
+       }
+       if !abiHashNoteFound {
+               t.Error("abi hash note not found")
+       }
+       if !depsNoteFound {
+               t.Error("deps note not found")
+       }
+}
+
+// Build a GOPATH package (depBase) into a shared library that links against the goroot
+// runtime, another package (dep2) that links against the first, and and an
+// executable that links against dep2.
+func TestTwoGopathShlibs(t *testing.T) {
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "dep2")
+       goCmd(t, "install", "-linkshared", "exe2")
+       run(t, "executable linked to GOPATH library", "./bin/exe2")
+}
+
+func TestThreeGopathShlibs(t *testing.T) {
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "dep2")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "dep3")
+       goCmd(t, "install", "-linkshared", "exe3")
+       run(t, "executable linked to GOPATH library", "./bin/exe3")
+}
+
+// If gccgo is not available or not new enough call t.Skip. Otherwise,
+// return a build.Context that is set up for gccgo.
+func prepGccgo(t *testing.T) build.Context {
+       gccgoName := os.Getenv("GCCGO")
+       if gccgoName == "" {
+               gccgoName = "gccgo"
+       }
+       gccgoPath, err := exec.LookPath(gccgoName)
+       if err != nil {
+               t.Skip("gccgo not found")
+       }
+       cmd := exec.Command(gccgoPath, "-dumpversion")
+       output, err := cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("%s -dumpversion failed: %v\n%s", gccgoPath, err, output)
+       }
+       if string(output) < "5" {
+               t.Skipf("gccgo too old (%s)", strings.TrimSpace(string(output)))
+       }
+       gccgoContext := build.Default
+       gccgoContext.InstallSuffix = suffix + "_fPIC"
+       gccgoContext.Compiler = "gccgo"
+       gccgoContext.GOPATH = os.Getenv("GOPATH")
+       return gccgoContext
+}
+
+// Build a GOPATH package into a shared library with gccgo and an executable that
+// links against it.
+func TestGoPathShlibGccgo(t *testing.T) {
+       gccgoContext := prepGccgo(t)
+
+       libgoRE := regexp.MustCompile("libgo.so.[0-9]+")
+
+       depP, err := gccgoContext.Import("depBase", ".", build.ImportComment)
+       if err != nil {
+               t.Fatalf("import failed: %v", err)
+       }
+       gccgoInstallDir := filepath.Join(depP.PkgTargetRoot, "shlibs")
+       goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "depBase")
+       AssertIsLinkedToRegexp(t, filepath.Join(gccgoInstallDir, "libdepBase.so"), libgoRE)
+       goCmd(t, "install", "-compiler=gccgo", "-linkshared", "exe")
+       AssertIsLinkedToRegexp(t, "./bin/exe", libgoRE)
+       AssertIsLinkedTo(t, "./bin/exe", "libdepBase.so")
+       AssertHasRPath(t, "./bin/exe", gccgoInstallDir)
+       // And check it runs.
+       run(t, "gccgo-built", "./bin/exe")
+}
+
+// The gccgo version of TestTwoGopathShlibs: build a GOPATH package into a shared
+// library with gccgo, another GOPATH package that depends on the first and an
+// executable that links the second library.
+func TestTwoGopathShlibsGccgo(t *testing.T) {
+       gccgoContext := prepGccgo(t)
+
+       libgoRE := regexp.MustCompile("libgo.so.[0-9]+")
+
+       depP, err := gccgoContext.Import("depBase", ".", build.ImportComment)
+       if err != nil {
+               t.Fatalf("import failed: %v", err)
+       }
+       gccgoInstallDir := filepath.Join(depP.PkgTargetRoot, "shlibs")
+       goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "depBase")
+       goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "dep2")
+       goCmd(t, "install", "-compiler=gccgo", "-linkshared", "exe2")
+
+       AssertIsLinkedToRegexp(t, filepath.Join(gccgoInstallDir, "libdepBase.so"), libgoRE)
+       AssertIsLinkedToRegexp(t, filepath.Join(gccgoInstallDir, "libdep2.so"), libgoRE)
+       AssertIsLinkedTo(t, filepath.Join(gccgoInstallDir, "libdep2.so"), "libdepBase.so")
+       AssertIsLinkedToRegexp(t, "./bin/exe2", libgoRE)
+       AssertIsLinkedTo(t, "./bin/exe2", "libdep2")
+       AssertIsLinkedTo(t, "./bin/exe2", "libdepBase.so")
+
+       // And check it runs.
+       run(t, "gccgo-built", "./bin/exe2")
+}
+
+// Testing rebuilding of shared libraries when they are stale is a bit more
+// complicated that it seems like it should be. First, we make everything "old": but
+// only a few seconds old, or it might be older than gc (or the runtime source) and
+// everything will get rebuilt. Then define a timestamp slightly newer than this
+// time, which is what we set the mtime to of a file to cause it to be seen as new,
+// and finally another slightly even newer one that we can compare files against to
+// see if they have been rebuilt.
+var oldTime = time.Now().Add(-9 * time.Second)
+var nearlyNew = time.Now().Add(-6 * time.Second)
+var stampTime = time.Now().Add(-3 * time.Second)
+
+// resetFileStamps makes "everything" (bin, src, pkg from GOPATH and the
+// test-specific parts of GOROOT) appear old.
+func resetFileStamps() {
+       chtime := func(path string, info os.FileInfo, err error) error {
+               return os.Chtimes(path, oldTime, oldTime)
+       }
+       reset := func(path string) {
+               if err := filepath.Walk(path, chtime); err != nil {
+                       log.Fatalf("resetFileStamps failed: %v", err)
+               }
+
+       }
+       reset("bin")
+       reset("pkg")
+       reset("src")
+       reset(gorootInstallDir)
+}
+
+// touch makes path newer than the "old" time stamp used by resetFileStamps.
+func touch(path string) {
+       if err := os.Chtimes(path, nearlyNew, nearlyNew); err != nil {
+               log.Fatalf("os.Chtimes failed: %v", err)
+       }
+}
+
+// isNew returns if the path is newer than the time stamp used by touch.
+func isNew(path string) bool {
+       fi, err := os.Stat(path)
+       if err != nil {
+               log.Fatalf("os.Stat failed: %v", err)
+       }
+       return fi.ModTime().After(stampTime)
+}
+
+// Fail unless path has been rebuilt (i.e. is newer than the time stamp used by
+// isNew)
+func AssertRebuilt(t *testing.T, msg, path string) {
+       if !isNew(path) {
+               t.Errorf("%s was not rebuilt (%s)", msg, path)
+       }
+}
+
+// Fail if path has been rebuilt (i.e. is newer than the time stamp used by isNew)
+func AssertNotRebuilt(t *testing.T, msg, path string) {
+       if isNew(path) {
+               t.Errorf("%s was rebuilt (%s)", msg, path)
+       }
+}
+
+func TestRebuilding(t *testing.T) {
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
+       goCmd(t, "install", "-linkshared", "exe")
+
+       // If the source is newer than both the .a file and the .so, both are rebuilt.
+       resetFileStamps()
+       touch("src/depBase/dep.go")
+       goCmd(t, "install", "-linkshared", "exe")
+       AssertRebuilt(t, "new source", filepath.Join(gopathInstallDir, "depBase.a"))
+       AssertRebuilt(t, "new source", filepath.Join(gopathInstallDir, "libdepBase.so"))
+
+       // If the .a file is newer than the .so, the .so is rebuilt (but not the .a)
+       resetFileStamps()
+       touch(filepath.Join(gopathInstallDir, "depBase.a"))
+       goCmd(t, "install", "-linkshared", "exe")
+       AssertNotRebuilt(t, "new .a file", filepath.Join(gopathInstallDir, "depBase.a"))
+       AssertRebuilt(t, "new .a file", filepath.Join(gopathInstallDir, "libdepBase.so"))
+}
+
+func appendFile(path, content string) {
+       f, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0660)
+       if err != nil {
+               log.Fatalf("os.OpenFile failed: %v", err)
+       }
+       defer func() {
+               err := f.Close()
+               if err != nil {
+                       log.Fatalf("f.Close failed: %v", err)
+               }
+       }()
+       _, err = f.WriteString(content)
+       if err != nil {
+               log.Fatalf("f.WriteString failed: %v", err)
+       }
+}
+
+func TestABIChecking(t *testing.T) {
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
+       goCmd(t, "install", "-linkshared", "exe")
+
+       // If we make an ABI-breaking change to depBase and rebuild libp.so but not exe,
+       // exe will abort with a complaint on startup.
+       // This assumes adding an exported function breaks ABI, which is not true in
+       // some senses but suffices for the narrow definition of ABI compatibility the
+       // toolchain uses today.
+       resetFileStamps()
+       appendFile("src/depBase/dep.go", "func ABIBreak() {}\n")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
+       c := exec.Command("./bin/exe")
+       output, err := c.CombinedOutput()
+       if err == nil {
+               t.Fatal("executing exe did not fail after ABI break")
+       }
+       scanner := bufio.NewScanner(bytes.NewReader(output))
+       foundMsg := false
+       const wantLine = "abi mismatch detected between the executable and libdepBase.so"
+       for scanner.Scan() {
+               if scanner.Text() == wantLine {
+                       foundMsg = true
+                       break
+               }
+       }
+       if err = scanner.Err(); err != nil {
+               t.Errorf("scanner encountered error: %v", err)
+       }
+       if !foundMsg {
+               t.Fatalf("exe failed, but without line %q; got output:\n%s", wantLine, output)
+       }
+
+       // Rebuilding exe makes it work again.
+       goCmd(t, "install", "-linkshared", "exe")
+       run(t, "rebuilt exe", "./bin/exe")
+
+       // If we make a change which does not break ABI (such as adding an unexported
+       // function) and rebuild libdepBase.so, exe still works.
+       resetFileStamps()
+       appendFile("src/depBase/dep.go", "func noABIBreak() {}\n")
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
+       run(t, "after non-ABI breaking change", "./bin/exe")
+}
+
+// If a package 'explicit' imports a package 'implicit', building
+// 'explicit' into a shared library implicitly includes implicit in
+// the shared library. Building an executable that imports both
+// explicit and implicit builds the code from implicit into the
+// executable rather than fetching it from the shared library. The
+// link still succeeds and the executable still runs though.
+func TestImplicitInclusion(t *testing.T) {
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "explicit")
+       goCmd(t, "install", "-linkshared", "implicitcmd")
+       run(t, "running executable linked against library that contains same package as it", "./bin/implicitcmd")
+}
+
+// Tests to make sure that the type fields of empty interfaces and itab
+// fields of nonempty interfaces are unique even across modules,
+// so that interface equality works correctly.
+func TestInterface(t *testing.T) {
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "iface_a")
+       // Note: iface_i gets installed implicitly as a dependency of iface_a.
+       goCmd(t, "install", "-buildmode=shared", "-linkshared", "iface_b")
+       goCmd(t, "install", "-linkshared", "iface")
+       run(t, "running type/itab uniqueness tester", "./bin/iface")
+}
diff --git a/libgo/misc/cgo/testshared/src/dep2/dep2.go b/libgo/misc/cgo/testshared/src/dep2/dep2.go
new file mode 100644 (file)
index 0000000..c2c812a
--- /dev/null
@@ -0,0 +1,15 @@
+package dep2
+
+import "depBase"
+
+var W int = 1
+
+var hasProg depBase.HasProg
+
+type Dep2 struct {
+       depBase.Dep
+}
+
+func G() int {
+       return depBase.F() + 1
+}
diff --git a/libgo/misc/cgo/testshared/src/dep3/dep3.go b/libgo/misc/cgo/testshared/src/dep3/dep3.go
new file mode 100644 (file)
index 0000000..7b7c9da
--- /dev/null
@@ -0,0 +1,22 @@
+package dep3
+
+// The point of this test file is that it references a type from
+// depBase that is also referenced in dep2, but dep2 is loaded by the
+// linker before depBase (because it is earlier in the import list).
+// There was a bug in the linker where it would not correctly read out
+// the type data in this case and later crash.
+
+import (
+       "dep2"
+       "depBase"
+)
+
+type Dep3 struct {
+       dep  depBase.Dep
+       dep2 dep2.Dep2
+}
+
+func D3() int {
+       var x Dep3
+       return x.dep.X + x.dep2.X
+}
diff --git a/libgo/misc/cgo/testshared/src/depBase/asm.s b/libgo/misc/cgo/testshared/src/depBase/asm.s
new file mode 100644 (file)
index 0000000..f203f8b
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2014 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 !gccgo
+
+#include "textflag.h"
+
+TEXT Â·ImplementedInAsm(SB),NOSPLIT,$0-0
+       RET
diff --git a/libgo/misc/cgo/testshared/src/depBase/dep.go b/libgo/misc/cgo/testshared/src/depBase/dep.go
new file mode 100644 (file)
index 0000000..9f86710
--- /dev/null
@@ -0,0 +1,33 @@
+package depBase
+
+import (
+       "os"
+       "reflect"
+)
+
+var SlicePtr interface{} = &[]int{}
+
+var V int = 1
+
+var HasMask []string = []string{"hi"}
+
+type HasProg struct {
+       array [1024]*byte
+}
+
+type Dep struct {
+       X int
+}
+
+func (d *Dep) Method() int {
+       // This code below causes various go.itab.* symbols to be generated in
+       // the shared library. Similar code in ../exe/exe.go results in
+       // exercising https://github.com/golang/go/issues/17594
+       reflect.TypeOf(os.Stdout).Elem()
+       return 10
+}
+
+func F() int {
+       defer func() {}()
+       return V
+}
diff --git a/libgo/misc/cgo/testshared/src/depBase/gccgo.go b/libgo/misc/cgo/testshared/src/depBase/gccgo.go
new file mode 100644 (file)
index 0000000..3e2b69b
--- /dev/null
@@ -0,0 +1,5 @@
+//+build gccgo
+
+package depBase
+
+func ImplementedInAsm() {}
diff --git a/libgo/misc/cgo/testshared/src/depBase/stubs.go b/libgo/misc/cgo/testshared/src/depBase/stubs.go
new file mode 100644 (file)
index 0000000..96573c1
--- /dev/null
@@ -0,0 +1,5 @@
+//+build !gccgo
+
+package depBase
+
+func ImplementedInAsm()
diff --git a/libgo/misc/cgo/testshared/src/exe/exe.go b/libgo/misc/cgo/testshared/src/exe/exe.go
new file mode 100644 (file)
index 0000000..84302a8
--- /dev/null
@@ -0,0 +1,44 @@
+package main
+
+import (
+       "depBase"
+       "os"
+       "reflect"
+       "runtime"
+)
+
+// Having a function declared in the main package triggered
+// golang.org/issue/18250
+func DeclaredInMain() {
+}
+
+type C struct {
+}
+
+func F() *C {
+       return nil
+}
+
+var slicePtr interface{} = &[]int{}
+
+func main() {
+       defer depBase.ImplementedInAsm()
+       // This code below causes various go.itab.* symbols to be generated in
+       // the executable. Similar code in ../depBase/dep.go results in
+       // exercising https://github.com/golang/go/issues/17594
+       reflect.TypeOf(os.Stdout).Elem()
+       runtime.GC()
+       depBase.V = depBase.F() + 1
+
+       var c *C
+       if reflect.TypeOf(F).Out(0) != reflect.TypeOf(c) {
+               panic("bad reflection results, see golang.org/issue/18252")
+       }
+
+       sp := reflect.New(reflect.TypeOf(slicePtr).Elem())
+       s := sp.Interface()
+
+       if reflect.TypeOf(s) != reflect.TypeOf(slicePtr) {
+               panic("bad reflection results, see golang.org/issue/18729")
+       }
+}
diff --git a/libgo/misc/cgo/testshared/src/exe2/exe2.go b/libgo/misc/cgo/testshared/src/exe2/exe2.go
new file mode 100644 (file)
index 0000000..675fd1f
--- /dev/null
@@ -0,0 +1,8 @@
+package main
+
+import "dep2"
+
+func main() {
+       d := &dep2.Dep2{}
+       dep2.W = dep2.G() + 1 + d.Method()
+}
diff --git a/libgo/misc/cgo/testshared/src/exe3/exe3.go b/libgo/misc/cgo/testshared/src/exe3/exe3.go
new file mode 100644 (file)
index 0000000..643f260
--- /dev/null
@@ -0,0 +1,7 @@
+package main
+
+import "dep3"
+
+func main() {
+       dep3.D3()
+}
diff --git a/libgo/misc/cgo/testshared/src/execgo/exe.go b/libgo/misc/cgo/testshared/src/execgo/exe.go
new file mode 100644 (file)
index 0000000..0427be8
--- /dev/null
@@ -0,0 +1,8 @@
+package main
+
+/*
+ */
+import "C"
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testshared/src/explicit/explicit.go b/libgo/misc/cgo/testshared/src/explicit/explicit.go
new file mode 100644 (file)
index 0000000..6a4453f
--- /dev/null
@@ -0,0 +1,9 @@
+package explicit
+
+import (
+       "implicit"
+)
+
+func E() int {
+       return implicit.I()
+}
diff --git a/libgo/misc/cgo/testshared/src/iface/main.go b/libgo/misc/cgo/testshared/src/iface/main.go
new file mode 100644 (file)
index 0000000..3d5b54e
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+package main
+
+import "iface_a"
+import "iface_b"
+
+func main() {
+       if iface_a.F() != iface_b.F() {
+               panic("empty interfaces not equal")
+       }
+       if iface_a.G() != iface_b.G() {
+               panic("non-empty interfaces not equal")
+       }
+}
diff --git a/libgo/misc/cgo/testshared/src/iface_a/a.go b/libgo/misc/cgo/testshared/src/iface_a/a.go
new file mode 100644 (file)
index 0000000..e11047c
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+package iface_a
+
+import "iface_i"
+
+//go:noinline
+func F() interface{} {
+       return (*iface_i.T)(nil)
+}
+
+//go:noinline
+func G() iface_i.I {
+       return (*iface_i.T)(nil)
+}
diff --git a/libgo/misc/cgo/testshared/src/iface_b/b.go b/libgo/misc/cgo/testshared/src/iface_b/b.go
new file mode 100644 (file)
index 0000000..47aee2e
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+package iface_b
+
+import "iface_i"
+
+//go:noinline
+func F() interface{} {
+       return (*iface_i.T)(nil)
+}
+
+//go:noinline
+func G() iface_i.I {
+       return (*iface_i.T)(nil)
+}
diff --git a/libgo/misc/cgo/testshared/src/iface_i/i.go b/libgo/misc/cgo/testshared/src/iface_i/i.go
new file mode 100644 (file)
index 0000000..31c8038
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+package iface_i
+
+type I interface {
+       M()
+}
+
+type T struct {
+}
+
+func (t *T) M() {
+}
+
+// *T implements I
diff --git a/libgo/misc/cgo/testshared/src/implicit/implicit.go b/libgo/misc/cgo/testshared/src/implicit/implicit.go
new file mode 100644 (file)
index 0000000..5360188
--- /dev/null
@@ -0,0 +1,5 @@
+package implicit
+
+func I() int {
+       return 42
+}
diff --git a/libgo/misc/cgo/testshared/src/implicitcmd/implicitcmd.go b/libgo/misc/cgo/testshared/src/implicitcmd/implicitcmd.go
new file mode 100644 (file)
index 0000000..f611293
--- /dev/null
@@ -0,0 +1,10 @@
+package main
+
+import (
+       "explicit"
+       "implicit"
+)
+
+func main() {
+       println(implicit.I() + explicit.E())
+}
diff --git a/libgo/misc/cgo/testshared/src/trivial/trivial.go b/libgo/misc/cgo/testshared/src/trivial/trivial.go
new file mode 100644 (file)
index 0000000..da29a2c
--- /dev/null
@@ -0,0 +1,4 @@
+package main
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testsigfwd/main.go b/libgo/misc/cgo/testsigfwd/main.go
new file mode 100644 (file)
index 0000000..61bd0da
--- /dev/null
@@ -0,0 +1,113 @@
+// Copyright 2015 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.
+
+package main
+
+import "fmt"
+
+/*
+#cgo CFLAGS: -pthread
+#cgo LDFLAGS: -pthread
+
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+
+int *p;
+static void sigsegv() {
+       *p = 1;
+       fprintf(stderr, "ERROR: C SIGSEGV not thrown on caught?.\n");
+       exit(2);
+}
+
+static void segvhandler(int signum) {
+       if (signum == SIGSEGV) {
+               exit(0);  // success
+       }
+}
+
+static volatile sig_atomic_t sigioSeen;
+
+// Use up some stack space.
+static void recur(int i, char *p) {
+       char a[1024];
+
+       *p = '\0';
+       if (i > 0) {
+               recur(i - 1, a);
+       }
+}
+
+static void iohandler(int signum) {
+       char a[1024];
+
+       recur(4, a);
+       sigioSeen = 1;
+}
+
+static void* sigioThread(void* arg __attribute__ ((unused))) {
+       raise(SIGIO);
+       return NULL;
+}
+
+static void sigioOnThread() {
+       pthread_t tid;
+       int i;
+
+       pthread_create(&tid, NULL, sigioThread, NULL);
+       pthread_join(tid, NULL);
+
+       // Wait until the signal has been delivered.
+       i = 0;
+       while (!sigioSeen) {
+               if (sched_yield() < 0) {
+                       perror("sched_yield");
+               }
+               i++;
+               if (i > 10000) {
+                       fprintf(stderr, "looping too long waiting for signal\n");
+                       exit(EXIT_FAILURE);
+               }
+       }
+}
+
+static void __attribute__ ((constructor)) sigsetup(void) {
+       struct sigaction act;
+
+       memset(&act, 0, sizeof act);
+       act.sa_handler = segvhandler;
+       sigaction(SIGSEGV, &act, NULL);
+
+       act.sa_handler = iohandler;
+       sigaction(SIGIO, &act, NULL);
+}
+*/
+import "C"
+
+var p *byte
+
+func f() (ret bool) {
+       defer func() {
+               if recover() == nil {
+                       fmt.Errorf("ERROR: couldn't raise SIGSEGV in Go.")
+                       C.exit(2)
+               }
+               ret = true
+       }()
+       *p = 1
+       return false
+}
+
+func main() {
+       // Test that the signal originating in Go is handled (and recovered) by Go.
+       if !f() {
+               fmt.Errorf("couldn't recover from SIGSEGV in Go.")
+               C.exit(2)
+       }
+
+       // Test that the signal originating in C is handled by C.
+       C.sigsegv()
+}
diff --git a/libgo/misc/cgo/testso/cgoso.c b/libgo/misc/cgo/testso/cgoso.c
new file mode 100644 (file)
index 0000000..917f472
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2013 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.
+
+#include "_cgo_export.h"
+
+#ifdef WIN32
+extern void setCallback(void *);
+void init() {
+       setCallback(goCallback);
+}
+#else
+void init() {}
+#endif
diff --git a/libgo/misc/cgo/testso/cgoso.go b/libgo/misc/cgo/testso/cgoso.go
new file mode 100644 (file)
index 0000000..29814fa
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2011 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.
+
+package cgosotest
+
+/*
+// intentionally write the same LDFLAGS differently
+// to test correct handling of LDFLAGS.
+#cgo linux LDFLAGS: -L. -lcgosotest
+#cgo dragonfly LDFLAGS: -L. -l cgosotest
+#cgo freebsd LDFLAGS: -L. -l cgosotest
+#cgo openbsd LDFLAGS: -L. -l cgosotest
+#cgo solaris LDFLAGS: -L. -lcgosotest
+#cgo netbsd LDFLAGS: -L. libcgosotest.so
+#cgo darwin LDFLAGS: -L. libcgosotest.dylib
+#cgo windows LDFLAGS: -L. libcgosotest.dll
+
+void init(void);
+void sofunc(void);
+*/
+import "C"
+
+func Test() {
+       C.init()
+       C.sofunc()
+}
+
+//export goCallback
+func goCallback() {
+}
diff --git a/libgo/misc/cgo/testso/cgoso_c.c b/libgo/misc/cgo/testso/cgoso_c.c
new file mode 100644 (file)
index 0000000..7a38022
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2011 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 ignore
+
+#ifdef WIN32
+// A Windows DLL is unable to call an arbitrary function in
+// the main executable. Work around that by making the main
+// executable pass the callback function pointer to us.
+void (*goCallback)(void);
+__declspec(dllexport) void setCallback(void *f)
+{
+       goCallback = (void (*)())f;
+}
+__declspec(dllexport) void sofunc(void);
+#else
+extern void goCallback(void);
+void setCallback(void *f) { (void)f; }
+#endif
+
+// OpenBSD and older Darwin lack TLS support
+#if !defined(__OpenBSD__) && !defined(__APPLE__)
+__thread int tlsvar = 12345;
+#endif
+
+void sofunc(void)
+{
+       goCallback();
+}
diff --git a/libgo/misc/cgo/testso/cgoso_unix.go b/libgo/misc/cgo/testso/cgoso_unix.go
new file mode 100644 (file)
index 0000000..49cdeaa
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2014 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 dragonfly freebsd linux netbsd solaris
+
+package cgosotest
+
+/*
+extern int __thread tlsvar;
+int *getTLS() { return &tlsvar; }
+*/
+import "C"
+
+func init() {
+       if v := *C.getTLS(); v != 12345 {
+               println("got", v)
+               panic("BAD TLS value")
+       }
+}
diff --git a/libgo/misc/cgo/testso/main.go b/libgo/misc/cgo/testso/main.go
new file mode 100644 (file)
index 0000000..88aa432
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2011 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 ignore
+
+package main
+
+import "."
+
+func main() {
+       cgosotest.Test()
+}
diff --git a/libgo/misc/cgo/testsovar/cgoso.go b/libgo/misc/cgo/testsovar/cgoso.go
new file mode 100644 (file)
index 0000000..88d44c2
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2015 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.
+
+package cgosotest
+
+// This test verifies that Go can access C variables
+// in shared object file via cgo.
+
+/*
+// intentionally write the same LDFLAGS differently
+// to test correct handling of LDFLAGS.
+#cgo windows CFLAGS: -DIMPORT_DLL
+#cgo linux LDFLAGS: -L. -lcgosotest
+#cgo dragonfly LDFLAGS: -L. -l cgosotest
+#cgo freebsd LDFLAGS: -L. -l cgosotest
+#cgo openbsd LDFLAGS: -L. -l cgosotest
+#cgo solaris LDFLAGS: -L. -lcgosotest
+#cgo netbsd LDFLAGS: -L. libcgosotest.so
+#cgo darwin LDFLAGS: -L. libcgosotest.dylib
+#cgo windows LDFLAGS: -L. libcgosotest.dll
+
+#include "cgoso_c.h"
+
+const char* getVar() {
+           return exported_var;
+}
+*/
+import "C"
+
+import "fmt"
+
+func Test() {
+       const want = "Hello world"
+       got := C.GoString(C.getVar())
+       if got != want {
+               panic(fmt.Sprintf("testExportedVar: got %q, but want %q", got, want))
+       }
+       got = C.GoString(C.exported_var)
+       if got != want {
+               panic(fmt.Sprintf("testExportedVar: got %q, but want %q", got, want))
+       }
+}
diff --git a/libgo/misc/cgo/testsovar/cgoso_c.c b/libgo/misc/cgo/testsovar/cgoso_c.c
new file mode 100644 (file)
index 0000000..a448c01
--- /dev/null
@@ -0,0 +1,7 @@
+// Copyright 2015 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 ignore
+
+const char *exported_var = "Hello world";
diff --git a/libgo/misc/cgo/testsovar/cgoso_c.h b/libgo/misc/cgo/testsovar/cgoso_c.h
new file mode 100644 (file)
index 0000000..640db7b
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2015 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 ignore
+
+#ifdef WIN32
+#if defined(EXPORT_DLL)
+#    define VAR __declspec(dllexport)
+#elif defined(IMPORT_DLL)
+#    define VAR __declspec(dllimport)
+#endif
+#else
+#    define VAR extern
+#endif
+
+VAR const char *exported_var;
diff --git a/libgo/misc/cgo/testsovar/main.go b/libgo/misc/cgo/testsovar/main.go
new file mode 100644 (file)
index 0000000..9c8a1c4
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2015 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 ignore
+
+package main
+
+import "."
+
+func main() {
+       cgosotest.Test()
+}
diff --git a/libgo/misc/cgo/testtls/tls.go b/libgo/misc/cgo/testtls/tls.go
new file mode 100644 (file)
index 0000000..e634220
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2013 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.
+
+package cgotlstest
+
+// #include <pthread.h>
+// extern void setTLS(int);
+// extern int getTLS();
+import "C"
+
+import (
+       "runtime"
+       "testing"
+)
+
+func testTLS(t *testing.T) {
+       runtime.LockOSThread()
+       defer runtime.UnlockOSThread()
+
+       if val := C.getTLS(); val != 0 {
+               t.Fatalf("at start, C.getTLS() = %#x, want 0", val)
+       }
+
+       const keyVal = 0x1234
+       C.setTLS(keyVal)
+       if val := C.getTLS(); val != keyVal {
+               t.Fatalf("at end, C.getTLS() = %#x, want %#x", val, keyVal)
+       }
+}
diff --git a/libgo/misc/cgo/testtls/tls_test.go b/libgo/misc/cgo/testtls/tls_test.go
new file mode 100644 (file)
index 0000000..3076c2d
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2013 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 !windows
+
+package cgotlstest
+
+import "testing"
+
+func TestTLS(t *testing.T) {
+       testTLS(t)
+}
diff --git a/libgo/misc/cgo/testtls/tls_unix.c b/libgo/misc/cgo/testtls/tls_unix.c
new file mode 100644 (file)
index 0000000..957afce
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2013 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.
+
+#include <pthread.h>
+
+static __thread int tls;
+
+void
+setTLS(int v)
+{
+       tls = v;
+}
+
+int
+getTLS()
+{
+       return tls;
+}