if gohostos == "linux" && goarch == "amd64" {
t.registerTest("testasan", "../misc/cgo/testasan", "go", "run", "main.go")
}
- if goos == "linux" && goarch == "amd64" {
+ if goos == "linux" && (goarch == "amd64" || goarch == "arm64") {
t.registerHostTest("testsanitizers/msan", "../misc/cgo/testsanitizers", "misc/cgo/testsanitizers", ".")
}
if t.hasBash() && goos != "android" && !t.iOS() && gohostos != "windows" {
// Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
// -msan
// enable interoperation with memory sanitizer.
-// Supported only on linux/amd64,
+// Supported only on linux/amd64, linux/arm64
// and only with Clang/LLVM as the host C compiler.
// -v
// print the names of packages as they are compiled.
Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
-msan
enable interoperation with memory sanitizer.
- Supported only on linux/amd64,
+ Supported only on linux/amd64, linux/arm64
and only with Clang/LLVM as the host C compiler.
-v
print the names of packages as they are compiled.
fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0])
os.Exit(2)
}
- if cfg.BuildMSan && (cfg.Goos != "linux" || cfg.Goarch != "amd64") {
+ if cfg.BuildMSan && (cfg.Goos != "linux" || cfg.Goarch != "amd64" && cfg.Goarch != "arm64") {
fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch)
os.Exit(2)
}
- if cfg.Goarch != "amd64" || cfg.Goos != "linux" && cfg.Goos != "freebsd" && cfg.Goos != "darwin" && cfg.Goos != "windows" {
- fmt.Fprintf(os.Stderr, "go %s: -race and -msan are only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
+ if cfg.BuildRace && (cfg.Goarch != "amd64" || cfg.Goos != "linux" && cfg.Goos != "freebsd" && cfg.Goos != "darwin" && cfg.Goos != "windows") {
+ fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
os.Exit(2)
}
// license that can be found in the LICENSE file.
#include <pthread.h>
+#include <errno.h>
#include <string.h>
#include <signal.h>
+#include <stdlib.h>
#include "libcgo.h"
#include "libcgo_unix.h"
void
x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase)
{
- pthread_attr_t attr;
+ pthread_attr_t *attr;
size_t size;
+ /* The memory sanitizer distributed with versions of clang
+ before 3.8 has a bug: if you call mmap before malloc, mmap
+ may return an address that is later overwritten by the msan
+ library. Avoid this problem by forcing a call to malloc
+ here, before we ever call malloc.
+
+ This is only required for the memory sanitizer, so it's
+ unfortunate that we always run it. It should be possible
+ to remove this when we no longer care about versions of
+ clang before 3.8. The test for this is
+ misc/cgo/testsanitizers.
+
+ GCC works hard to eliminate a seemingly unnecessary call to
+ malloc, so we actually use the memory we allocate. */
+
setg_gcc = setg;
- pthread_attr_init(&attr);
- pthread_attr_getstacksize(&attr, &size);
- g->stacklo = (uintptr)&attr - size + 4096;
- pthread_attr_destroy(&attr);
+ attr = (pthread_attr_t*)malloc(sizeof *attr);
+ if (attr == NULL) {
+ fatalf("malloc failed: %s", strerror(errno));
+ }
+ pthread_attr_init(attr);
+ pthread_attr_getstacksize(attr, &size);
+ g->stacklo = (uintptr)&size - size + 4096;
+ pthread_attr_destroy(attr);
+ free(attr);
if (x_cgo_inittls) {
x_cgo_inittls(tlsg, tlsbase);
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build linux,amd64
+// +build linux,amd64 linux,arm64
#include <errno.h>
#include <stdint.h>
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build linux,amd64
+// +build linux,amd64 linux,arm64
#include <errno.h>
#include <stddef.h>
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build linux,amd64
+// +build linux,amd64 linux,arm64
package cgo
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build linux,amd64 freebsd,amd64
+// +build linux,amd64 freebsd,amd64 linux,arm64
package cgo
// Support for memory sanitizer. See runtime/cgo/mmap.go.
-// +build linux,amd64
+// +build linux,amd64 linux,arm64
package runtime
// Support for memory sanitizer. See runtime/cgo/sigaction.go.
-// +build linux,amd64 freebsd,amd64
+// +build linux,amd64 freebsd,amd64 linux,arm64
package runtime
// +build !windows
// +build !nacl
// +build !linux !amd64
+// +build !linux !arm64
package runtime
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build msan,linux,amd64
+// +build msan,linux
+// +build amd64 arm64
package msan
--- /dev/null
+// Copyright 2018 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 msan
+
+#include "go_asm.h"
+#include "textflag.h"
+
+#define RARG0 R0
+#define RARG1 R1
+#define FARG R3
+
+// func runtime·domsanread(addr unsafe.Pointer, sz uintptr)
+// Called from msanread.
+TEXT runtime·domsanread(SB), NOSPLIT, $0-16
+ MOVD addr+0(FP), RARG0
+ MOVD size+8(FP), RARG1
+ // void __msan_read_go(void *addr, uintptr_t sz);
+ MOVD $__msan_read_go(SB), FARG
+ JMP msancall<>(SB)
+
+// func runtime·msanwrite(addr unsafe.Pointer, sz uintptr)
+// Called from instrumented code.
+TEXT runtime·msanwrite(SB), NOSPLIT, $0-16
+ MOVD addr+0(FP), RARG0
+ MOVD size+8(FP), RARG1
+ // void __msan_write_go(void *addr, uintptr_t sz);
+ MOVD $__msan_write_go(SB), FARG
+ JMP msancall<>(SB)
+
+// func runtime·msanmalloc(addr unsafe.Pointer, sz uintptr)
+TEXT runtime·msanmalloc(SB), NOSPLIT, $0-16
+ MOVD addr+0(FP), RARG0
+ MOVD size+8(FP), RARG1
+ // void __msan_malloc_go(void *addr, uintptr_t sz);
+ MOVD $__msan_malloc_go(SB), FARG
+ JMP msancall<>(SB)
+
+// func runtime·msanfree(addr unsafe.Pointer, sz uintptr)
+TEXT runtime·msanfree(SB), NOSPLIT, $0-16
+ MOVD addr+0(FP), RARG0
+ MOVD size+8(FP), RARG1
+ // void __msan_free_go(void *addr, uintptr_t sz);
+ MOVD $__msan_free_go(SB), FARG
+ JMP msancall<>(SB)
+
+// Switches SP to g0 stack and calls (FARG). Arguments already set.
+TEXT msancall<>(SB), NOSPLIT, $0-0
+ MOVD g_m(g), R10
+ MOVD m_g0(R10), R11
+ MOVD RSP, R19 // callee-saved
+ CMP R11, g
+ BEQ g0stack
+
+ MOVD (g_sched+gobuf_sp)(R11), R4
+ MOVD R4, RSP
+
+g0stack:
+ BL (FARG)
+ MOVD R19, RSP
+ RET
// When building with -buildmode=c-shared, this symbol is called when the shared
// library is loaded.
-TEXT _rt0_arm64_linux_lib(SB),NOSPLIT,$168
+TEXT _rt0_arm64_linux_lib(SB),NOSPLIT,$184
// Preserve callee-save registers.
MOVD R19, 24(RSP)
MOVD R20, 32(RSP)
FMOVD F13, 136(RSP)
FMOVD F14, 144(RSP)
FMOVD F15, 152(RSP)
+ MOVD g, 160(RSP)
+
+ // Initialize g as null in case of using g later e.g. sigaction in cgo_sigaction.go
+ MOVD ZR, g
MOVD R0, _rt0_arm64_linux_lib_argc<>(SB)
MOVD R1, _rt0_arm64_linux_lib_argv<>(SB)
FMOVD 136(RSP), F13
FMOVD 144(RSP), F14
FMOVD 152(RSP), F15
+ MOVD 160(RSP), g
RET
TEXT _rt0_arm64_linux_lib_go(SB),NOSPLIT,$0
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build linux,!amd64 freebsd,!amd64
+// +build linux,!amd64,!arm64 freebsd,!amd64
package runtime
MOVW R0, ret+32(FP)
RET
+// Call the function stored in _cgo_sigaction using the GCC calling convention.
+TEXT runtime·callCgoSigaction(SB),NOSPLIT,$0
+ MOVD sig+0(FP), R0
+ MOVD new+8(FP), R1
+ MOVD old+16(FP), R2
+ MOVD _cgo_sigaction(SB), R3
+ BL R3
+ MOVW R0, ret+24(FP)
+ RET
+
TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
MOVW sig+8(FP), R0
MOVD info+16(FP), R1
MOVD $runtime·sigtramp(SB), R3
B (R3)
-TEXT runtime·mmap(SB),NOSPLIT|NOFRAME,$0
+TEXT runtime·sysMmap(SB),NOSPLIT|NOFRAME,$0
MOVD addr+0(FP), R0
MOVD n+8(FP), R1
MOVW prot+16(FP), R2
MOVD $0, err+40(FP)
RET
-TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0
+// Call the function stored in _cgo_mmap using the GCC calling convention.
+// This must be called on the system stack.
+TEXT runtime·callCgoMmap(SB),NOSPLIT,$0
+ MOVD addr+0(FP), R0
+ MOVD n+8(FP), R1
+ MOVW prot+16(FP), R2
+ MOVW flags+20(FP), R3
+ MOVW fd+24(FP), R4
+ MOVW off+28(FP), R5
+ MOVD _cgo_mmap(SB), R9
+ BL R9
+ MOVD R0, ret+32(FP)
+ RET
+
+TEXT runtime·sysMunmap(SB),NOSPLIT|NOFRAME,$0
MOVD addr+0(FP), R0
MOVD n+8(FP), R1
MOVD $SYS_munmap, R8
cool:
RET
+// Call the function stored in _cgo_munmap using the GCC calling convention.
+// This must be called on the system stack.
+TEXT runtime·callCgoMunmap(SB),NOSPLIT,$0
+ MOVD addr+0(FP), R0
+ MOVD n+8(FP), R1
+ MOVD _cgo_munmap(SB), R9
+ BL R9
+ RET
+
TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
MOVD addr+0(FP), R0
MOVD n+8(FP), R1