From c8dc49fb0318088e30040d1162cea181931f1ab4 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 12 Oct 2016 14:28:05 +0000 Subject: [PATCH] syscall, internal/syscall/unix: Fix getrandom, clone on sparc64 Since sparc is a valid architecture, the name of getrandom_linux_sparc.go means that it will be ignored on sparc64, even though it's whitelisted with a +build line. On SPARC, clone has a unique return value convention which requires some inline assembly to convert it to the normal convention. Reviewed-on: https://go-review.googlesource.com/30873 From-SVN: r241051 --- gcc/go/gofrontend/MERGE | 2 +- libgo/Makefile.am | 10 ++ libgo/Makefile.in | 43 ++++---- ...nux_sparc.go => getrandom_linux_sparcx.go} | 0 libgo/go/syscall/clone_linux.c | 100 ++++++++++++++++++ libgo/go/syscall/exec_linux.go | 19 ++-- libgo/mksysinfo.sh | 2 + 7 files changed, 147 insertions(+), 29 deletions(-) rename libgo/go/internal/syscall/unix/{getrandom_linux_sparc.go => getrandom_linux_sparcx.go} (100%) create mode 100644 libgo/go/syscall/clone_linux.c diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index d09cec1414e..d022604cc46 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -03e53c928ebaa15a915eb1e1b07f193d83fc2852 +d56717f8c434b3d6b753c027487681769e201e14 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/libgo/Makefile.am b/libgo/Makefile.am index b7c3e1810dc..b4243e77ae8 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -736,6 +736,12 @@ s-epoll: Makefile $(SHELL) $(srcdir)/mvifdiff.sh epoll.go.tmp epoll.go $(STAMP) $@ +if LIBGO_IS_LINUX +syscall_lib_clone_lo = syscall/clone_linux.lo +else +syscall_lib_clone_lo = +endif + libgo_go_objs = \ bufio.lo \ bytes.lo \ @@ -767,6 +773,7 @@ libgo_go_objs = \ strings/index.lo \ sync.lo \ syscall.lo \ + $(syscall_lib_clone_lo) \ syscall/errno.lo \ syscall/signame.lo \ syscall/wait.lo \ @@ -2534,6 +2541,9 @@ syscall.lo.dep: $(srcdir)/go/syscall/*.go $(extra_go_files_syscall) $(BUILDDEPS) syscall.lo: $(BUILDPACKAGE) +syscall/clone_linux.lo: go/syscall/clone_linux.c runtime.inc + @$(MKDIR_P) syscall + $(LTCOMPILE) -c -o $@ $< syscall/errno.lo: go/syscall/errno.c runtime.inc @$(MKDIR_P) syscall $(LTCOMPILE) -c -o $@ $< diff --git a/libgo/Makefile.in b/libgo/Makefile.in index e6571cd6d0c..5c824e5c0b3 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -168,21 +168,22 @@ libnetgo_a_DEPENDENCIES = netgo.o am_libnetgo_a_OBJECTS = libnetgo_a_OBJECTS = $(am_libnetgo_a_OBJECTS) LTLIBRARIES = $(toolexeclib_LTLIBRARIES) -am__DEPENDENCIES_1 = bufio.lo bytes.lo bytes/index.lo context.lo \ +@LIBGO_IS_LINUX_TRUE@am__DEPENDENCIES_1 = syscall/clone_linux.lo +am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo context.lo \ crypto.lo encoding.lo errors.lo expvar.lo flag.lo fmt.lo \ hash.lo html.lo image.lo io.lo log.lo math.lo mime.lo net.lo \ os.lo path.lo reflect-go.lo reflect/makefunc_ffi_c.lo \ regexp.lo runtime-go.lo sort.lo strconv.lo strings.lo \ - strings/index.lo sync.lo syscall.lo syscall/errno.lo \ - syscall/signame.lo syscall/wait.lo testing.lo time-go.lo \ - unicode.lo archive/tar.lo archive/zip.lo compress/bzip2.lo \ - compress/flate.lo compress/gzip.lo compress/lzw.lo \ - compress/zlib.lo container/heap.lo container/list.lo \ - container/ring.lo crypto/aes.lo crypto/cipher.lo crypto/des.lo \ - crypto/dsa.lo crypto/ecdsa.lo crypto/elliptic.lo \ - crypto/hmac.lo crypto/md5.lo crypto/rand.lo crypto/rc4.lo \ - crypto/rsa.lo crypto/sha1.lo crypto/sha256.lo crypto/sha512.lo \ - crypto/subtle.lo crypto/tls.lo crypto/x509.lo \ + strings/index.lo sync.lo syscall.lo $(am__DEPENDENCIES_1) \ + syscall/errno.lo syscall/signame.lo syscall/wait.lo testing.lo \ + time-go.lo unicode.lo archive/tar.lo archive/zip.lo \ + compress/bzip2.lo compress/flate.lo compress/gzip.lo \ + compress/lzw.lo compress/zlib.lo container/heap.lo \ + container/list.lo container/ring.lo crypto/aes.lo \ + crypto/cipher.lo crypto/des.lo crypto/dsa.lo crypto/ecdsa.lo \ + crypto/elliptic.lo crypto/hmac.lo crypto/md5.lo crypto/rand.lo \ + crypto/rc4.lo crypto/rsa.lo crypto/sha1.lo crypto/sha256.lo \ + crypto/sha512.lo crypto/subtle.lo crypto/tls.lo crypto/x509.lo \ crypto/x509/pkix.lo database/sql.lo database/sql/driver.lo \ debug/dwarf.lo debug/elf.lo debug/gosym.lo debug/macho.lo \ debug/pe.lo debug/plan9obj.lo encoding/ascii85.lo \ @@ -217,12 +218,12 @@ am__DEPENDENCIES_1 = bufio.lo bytes.lo bytes/index.lo context.lo \ text/scanner.lo text/tabwriter.lo text/template.lo \ text/template/parse.lo testing/iotest.lo testing/quick.lo \ unicode/utf16.lo unicode/utf8.lo -am__DEPENDENCIES_2 = -am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) \ - ../libbacktrace/libbacktrace.la $(am__DEPENDENCIES_2) \ - $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_2) \ - $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_2) -libgo_llgo_la_DEPENDENCIES = $(am__DEPENDENCIES_3) +am__DEPENDENCIES_3 = +am__DEPENDENCIES_4 = $(am__DEPENDENCIES_2) \ + ../libbacktrace/libbacktrace.la $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_3) +libgo_llgo_la_DEPENDENCIES = $(am__DEPENDENCIES_4) @HAVE_SYS_MMAN_H_FALSE@am__objects_1 = mem_posix_memalign.lo @HAVE_SYS_MMAN_H_TRUE@am__objects_1 = mem.lo @LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_2 = netpoll_kqueue.lo @@ -272,7 +273,7 @@ libgo_llgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgo_llgo_la_LDFLAGS) $(LDFLAGS) -o $@ @GOC_IS_LLGO_TRUE@am_libgo_llgo_la_rpath = -rpath $(toolexeclibdir) -libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_3) +libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_4) am_libgo_la_OBJECTS = $(am__objects_6) libgo_la_OBJECTS = $(am_libgo_la_OBJECTS) libgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ @@ -948,6 +949,8 @@ SYSINFO_FLAGS = \ $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(OSCFLAGS) -O +@LIBGO_IS_LINUX_FALSE@syscall_lib_clone_lo = +@LIBGO_IS_LINUX_TRUE@syscall_lib_clone_lo = syscall/clone_linux.lo libgo_go_objs = \ bufio.lo \ bytes.lo \ @@ -979,6 +982,7 @@ libgo_go_objs = \ strings/index.lo \ sync.lo \ syscall.lo \ + $(syscall_lib_clone_lo) \ syscall/errno.lo \ syscall/signame.lo \ syscall/wait.lo \ @@ -5109,6 +5113,9 @@ syscall.lo.dep: $(srcdir)/go/syscall/*.go $(extra_go_files_syscall) $(BUILDDEPS) syscall.lo: $(BUILDPACKAGE) +syscall/clone_linux.lo: go/syscall/clone_linux.c runtime.inc + @$(MKDIR_P) syscall + $(LTCOMPILE) -c -o $@ $< syscall/errno.lo: go/syscall/errno.c runtime.inc @$(MKDIR_P) syscall $(LTCOMPILE) -c -o $@ $< diff --git a/libgo/go/internal/syscall/unix/getrandom_linux_sparc.go b/libgo/go/internal/syscall/unix/getrandom_linux_sparcx.go similarity index 100% rename from libgo/go/internal/syscall/unix/getrandom_linux_sparc.go rename to libgo/go/internal/syscall/unix/getrandom_linux_sparcx.go diff --git a/libgo/go/syscall/clone_linux.c b/libgo/go/syscall/clone_linux.c new file mode 100644 index 00000000000..a1a15ea05d8 --- /dev/null +++ b/libgo/go/syscall/clone_linux.c @@ -0,0 +1,100 @@ +/* clone_linux.c -- consistent wrapper around Linux clone syscall + + 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. */ + +#include +#include +#include + +#include "runtime.h" + +long rawClone (unsigned long flags, void *child_stack, void *ptid, void *ctid, struct pt_regs *regs) __asm__ (GOSYM_PREFIX "syscall.rawClone"); + +long +rawClone (unsigned long flags, void *child_stack, void *ptid, void *ctid, struct pt_regs *regs) +{ +#if defined(__arc__) || defined(__aarch64__) || defined(__arm__) || defined(__mips__) || defined(__hppa__) || defined(__powerpc__) || defined(__score__) || defined(__i386__) || defined(__xtensa__) + // CLONE_BACKWARDS + return syscall(__NR_clone, flags, child_stack, ptid, regs, ctid); +#elif defined(__s390__) || defined(__cris__) + // CLONE_BACKWARDS2 + return syscall(__NR_clone, child_stack, flags, ptid, ctid, regs); +#elif defined(__microblaze__) + // CLONE_BACKWARDS3 + return syscall(__NR_clone, flags, child_stack, 0, ptid, ctid, regs); +#elif defined(__sparc__) + + /* SPARC has a unique return value convention: + + Parent --> %o0 == child's pid, %o1 == 0 + Child --> %o0 == parent's pid, %o1 == 1 + + Translate this to look like a normal clone. */ + +# if defined(__arch64__) + +# define SYSCALL_STRING \ + "ta 0x6d;" \ + "bcc,pt %%xcc, 1f;" \ + " mov 0, %%g1;" \ + "sub %%g0, %%o0, %%o0;" \ + "mov 1, %%g1;" \ + "1:" + +# define SYSCALL_CLOBBERS \ + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", \ + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", \ + "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46", \ + "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62", \ + "cc", "memory" + +# else /* __arch64__ */ + +# define SYSCALL_STRING \ + "ta 0x10;" \ + "bcc 1f;" \ + " mov 0, %%g1;" \ + "sub %%g0, %%o0, %%o0;" \ + "mov 1, %%g1;" \ + "1:" + +# define SYSCALL_CLOBBERS \ + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", \ + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", \ + "cc", "memory" + +# endif /* __arch64__ */ + + register long o0 __asm__ ("o0") = (long)flags; + register long o1 __asm__ ("o1") = (long)child_stack; + register long o2 __asm__ ("o2") = (long)ptid; + register long o3 __asm__ ("o3") = (long)ctid; + register long o4 __asm__ ("o4") = (long)regs; + register long g1 __asm__ ("g1") = __NR_clone; + + __asm __volatile (SYSCALL_STRING : + "=r" (g1), "=r" (o0), "=r" (o1) : + "0" (g1), "1" (o0), "2" (o1), + "r" (o2), "r" (o3), "r" (o4) : + SYSCALL_CLOBBERS); + + if (__builtin_expect(g1 != 0, 0)) + { + errno = -o0; + o0 = -1L; + } + else + o0 &= (o1 - 1); + + return o0; + +#else + return syscall(__NR_clone, flags, child_stack, ptid, ctid, regs); +#endif +} diff --git a/libgo/go/syscall/exec_linux.go b/libgo/go/syscall/exec_linux.go index 581a9886dcf..83d9c1ca2db 100644 --- a/libgo/go/syscall/exec_linux.go +++ b/libgo/go/syscall/exec_linux.go @@ -7,7 +7,6 @@ package syscall import ( - "runtime" "unsafe" ) @@ -49,6 +48,9 @@ type SysProcAttr struct { func runtime_BeforeFork() func runtime_AfterFork() +// Implemented in clone_linux.c +func rawClone(flags _C_ulong, child_stack *byte, ptid *Pid_t, ctid *Pid_t, regs unsafe.Pointer) _C_long + // Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child. // If a dup or exec fails, write the errno error to pipe. // (Pipe is close-on-exec so if exec succeeds, it will be closed.) @@ -64,6 +66,7 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr // declarations require heap allocation (e.g., err1). var ( r1 uintptr + r2 _C_long err1 Errno err2 Errno nextfd int @@ -98,20 +101,16 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr // About to call fork. // No more allocation or calls of non-assembly functions. runtime_BeforeFork() - if runtime.GOARCH == "s390x" || runtime.GOARCH == "s390" { - r1, _, err1 = RawSyscall6(SYS_CLONE, 0, uintptr(SIGCHLD)|sys.Cloneflags, 0, 0, 0, 0) - } else { - r1, _, err1 = RawSyscall6(SYS_CLONE, uintptr(SIGCHLD)|sys.Cloneflags, 0, 0, 0, 0, 0) - } - if err1 != 0 { + r2 = rawClone(_C_ulong(uintptr(SIGCHLD)|sys.Cloneflags), nil, nil, nil, unsafe.Pointer(nil)) + if r2 < 0 { runtime_AfterFork() - return 0, err1 + return 0, GetErrno() } - if r1 != 0 { + if r2 != 0 { // parent; return PID runtime_AfterFork() - pid = int(r1) + pid = int(r2) if sys.UidMappings != nil || sys.GidMappings != nil { Close(p[0]) diff --git a/libgo/mksysinfo.sh b/libgo/mksysinfo.sh index eeac94a3ecf..f79b5cfd7d8 100755 --- a/libgo/mksysinfo.sh +++ b/libgo/mksysinfo.sh @@ -349,8 +349,10 @@ fi sizeof_long=`grep '^const ___SIZEOF_LONG__ = ' gen-sysinfo.go | sed -e 's/.*= //'` if test "$sizeof_long" = "4"; then echo "type _C_long int32" >> ${OUT} + echo "type _C_ulong uint32" >> ${OUT} elif test "$sizeof_long" = "8"; then echo "type _C_long int64" >> ${OUT} + echo "type _C_ulong uint64" >> ${OUT} else echo 1>&2 "mksysinfo.sh: could not determine size of long (got $sizeof_long)" exit 1 -- 2.30.2