Skip to content

Commit e8d417d

Browse files
zorrorffmianlancetaylor
authored andcommitted
runtime: enable memory sanitizer on arm64
Changes include: 1. open compilation option -msan for arm64 2. modify doc to explain -msan is also supported on linux/arm64 3. wrap msan lib API in msan_arm64.s 4. use libc for sigaction syscalls when cgo is enabled 5. use libc for mmap syscalls when cgo is enabled Change-Id: I26ebe61ff7ce1906125f54a0182a720f9d58ec11 Reviewed-on: https://go-review.googlesource.com/109255 Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent eff1e68 commit e8d417d

17 files changed

+146
-22
lines changed

src/cmd/dist/test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,7 @@ func (t *tester) registerTests() {
676676
if gohostos == "linux" && goarch == "amd64" {
677677
t.registerTest("testasan", "../misc/cgo/testasan", "go", "run", "main.go")
678678
}
679-
if goos == "linux" && goarch == "amd64" {
679+
if goos == "linux" && (goarch == "amd64" || goarch == "arm64") {
680680
t.registerHostTest("testsanitizers/msan", "../misc/cgo/testsanitizers", "misc/cgo/testsanitizers", ".")
681681
}
682682
if t.hasBash() && goos != "android" && !t.iOS() && gohostos != "windows" {

src/cmd/go/alldocs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@
105105
// Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
106106
// -msan
107107
// enable interoperation with memory sanitizer.
108-
// Supported only on linux/amd64,
108+
// Supported only on linux/amd64, linux/arm64
109109
// and only with Clang/LLVM as the host C compiler.
110110
// -v
111111
// print the names of packages as they are compiled.

src/cmd/go/internal/work/build.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ and test commands:
6565
Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
6666
-msan
6767
enable interoperation with memory sanitizer.
68-
Supported only on linux/amd64,
68+
Supported only on linux/amd64, linux/arm64
6969
and only with Clang/LLVM as the host C compiler.
7070
-v
7171
print the names of packages as they are compiled.

src/cmd/go/internal/work/init.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ func instrumentInit() {
3939
fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0])
4040
os.Exit(2)
4141
}
42-
if cfg.BuildMSan && (cfg.Goos != "linux" || cfg.Goarch != "amd64") {
42+
if cfg.BuildMSan && (cfg.Goos != "linux" || cfg.Goarch != "amd64" && cfg.Goarch != "arm64") {
4343
fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch)
4444
os.Exit(2)
4545
}
46-
if cfg.Goarch != "amd64" || cfg.Goos != "linux" && cfg.Goos != "freebsd" && cfg.Goos != "darwin" && cfg.Goos != "windows" {
47-
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])
46+
if cfg.BuildRace && (cfg.Goarch != "amd64" || cfg.Goos != "linux" && cfg.Goos != "freebsd" && cfg.Goos != "darwin" && cfg.Goos != "windows") {
47+
fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
4848
os.Exit(2)
4949
}
5050

src/runtime/cgo/gcc_linux_arm64.c

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
// license that can be found in the LICENSE file.
44

55
#include <pthread.h>
6+
#include <errno.h>
67
#include <string.h>
78
#include <signal.h>
9+
#include <stdlib.h>
810
#include "libcgo.h"
911
#include "libcgo_unix.h"
1012

@@ -59,14 +61,34 @@ threadentry(void *v)
5961
void
6062
x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase)
6163
{
62-
pthread_attr_t attr;
64+
pthread_attr_t *attr;
6365
size_t size;
6466

67+
/* The memory sanitizer distributed with versions of clang
68+
before 3.8 has a bug: if you call mmap before malloc, mmap
69+
may return an address that is later overwritten by the msan
70+
library. Avoid this problem by forcing a call to malloc
71+
here, before we ever call malloc.
72+
73+
This is only required for the memory sanitizer, so it's
74+
unfortunate that we always run it. It should be possible
75+
to remove this when we no longer care about versions of
76+
clang before 3.8. The test for this is
77+
misc/cgo/testsanitizers.
78+
79+
GCC works hard to eliminate a seemingly unnecessary call to
80+
malloc, so we actually use the memory we allocate. */
81+
6582
setg_gcc = setg;
66-
pthread_attr_init(&attr);
67-
pthread_attr_getstacksize(&attr, &size);
68-
g->stacklo = (uintptr)&attr - size + 4096;
69-
pthread_attr_destroy(&attr);
83+
attr = (pthread_attr_t*)malloc(sizeof *attr);
84+
if (attr == NULL) {
85+
fatalf("malloc failed: %s", strerror(errno));
86+
}
87+
pthread_attr_init(attr);
88+
pthread_attr_getstacksize(attr, &size);
89+
g->stacklo = (uintptr)&size - size + 4096;
90+
pthread_attr_destroy(attr);
91+
free(attr);
7092

7193
if (x_cgo_inittls) {
7294
x_cgo_inittls(tlsg, tlsbase);

src/runtime/cgo/gcc_mmap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build linux,amd64
5+
// +build linux,amd64 linux,arm64
66

77
#include <errno.h>
88
#include <stdint.h>

src/runtime/cgo/gcc_sigaction.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build linux,amd64
5+
// +build linux,amd64 linux,arm64
66

77
#include <errno.h>
88
#include <stddef.h>

src/runtime/cgo/mmap.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build linux,amd64
5+
// +build linux,amd64 linux,arm64
66

77
package cgo
88

src/runtime/cgo/sigaction.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build linux,amd64 freebsd,amd64
5+
// +build linux,amd64 freebsd,amd64 linux,arm64
66

77
package cgo
88

src/runtime/cgo_mmap.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
// Support for memory sanitizer. See runtime/cgo/mmap.go.
66

7-
// +build linux,amd64
7+
// +build linux,amd64 linux,arm64
88

99
package runtime
1010

src/runtime/cgo_sigaction.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
// Support for memory sanitizer. See runtime/cgo/sigaction.go.
66

7-
// +build linux,amd64 freebsd,amd64
7+
// +build linux,amd64 freebsd,amd64 linux,arm64
88

99
package runtime
1010

src/runtime/mmap.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
// +build !windows
88
// +build !nacl
99
// +build !linux !amd64
10+
// +build !linux !arm64
1011

1112
package runtime
1213

src/runtime/msan/msan.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build msan,linux,amd64
5+
// +build msan,linux
6+
// +build amd64 arm64
67

78
package msan
89

src/runtime/msan_arm64.s

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2018 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// +build msan
6+
7+
#include "go_asm.h"
8+
#include "textflag.h"
9+
10+
#define RARG0 R0
11+
#define RARG1 R1
12+
#define FARG R3
13+
14+
// func runtime·domsanread(addr unsafe.Pointer, sz uintptr)
15+
// Called from msanread.
16+
TEXT runtime·domsanread(SB), NOSPLIT, $0-16
17+
MOVD addr+0(FP), RARG0
18+
MOVD size+8(FP), RARG1
19+
// void __msan_read_go(void *addr, uintptr_t sz);
20+
MOVD $__msan_read_go(SB), FARG
21+
JMP msancall<>(SB)
22+
23+
// func runtime·msanwrite(addr unsafe.Pointer, sz uintptr)
24+
// Called from instrumented code.
25+
TEXT runtime·msanwrite(SB), NOSPLIT, $0-16
26+
MOVD addr+0(FP), RARG0
27+
MOVD size+8(FP), RARG1
28+
// void __msan_write_go(void *addr, uintptr_t sz);
29+
MOVD $__msan_write_go(SB), FARG
30+
JMP msancall<>(SB)
31+
32+
// func runtime·msanmalloc(addr unsafe.Pointer, sz uintptr)
33+
TEXT runtime·msanmalloc(SB), NOSPLIT, $0-16
34+
MOVD addr+0(FP), RARG0
35+
MOVD size+8(FP), RARG1
36+
// void __msan_malloc_go(void *addr, uintptr_t sz);
37+
MOVD $__msan_malloc_go(SB), FARG
38+
JMP msancall<>(SB)
39+
40+
// func runtime·msanfree(addr unsafe.Pointer, sz uintptr)
41+
TEXT runtime·msanfree(SB), NOSPLIT, $0-16
42+
MOVD addr+0(FP), RARG0
43+
MOVD size+8(FP), RARG1
44+
// void __msan_free_go(void *addr, uintptr_t sz);
45+
MOVD $__msan_free_go(SB), FARG
46+
JMP msancall<>(SB)
47+
48+
// Switches SP to g0 stack and calls (FARG). Arguments already set.
49+
TEXT msancall<>(SB), NOSPLIT, $0-0
50+
MOVD g_m(g), R10
51+
MOVD m_g0(R10), R11
52+
MOVD RSP, R19 // callee-saved
53+
CMP R11, g
54+
BEQ g0stack
55+
56+
MOVD (g_sched+gobuf_sp)(R11), R4
57+
MOVD R4, RSP
58+
59+
g0stack:
60+
BL (FARG)
61+
MOVD R19, RSP
62+
RET

src/runtime/rt0_linux_arm64.s

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ TEXT _rt0_arm64_linux(SB),NOSPLIT|NOFRAME,$0
1111

1212
// When building with -buildmode=c-shared, this symbol is called when the shared
1313
// library is loaded.
14-
TEXT _rt0_arm64_linux_lib(SB),NOSPLIT,$168
14+
TEXT _rt0_arm64_linux_lib(SB),NOSPLIT,$184
1515
// Preserve callee-save registers.
1616
MOVD R19, 24(RSP)
1717
MOVD R20, 32(RSP)
@@ -30,6 +30,10 @@ TEXT _rt0_arm64_linux_lib(SB),NOSPLIT,$168
3030
FMOVD F13, 136(RSP)
3131
FMOVD F14, 144(RSP)
3232
FMOVD F15, 152(RSP)
33+
MOVD g, 160(RSP)
34+
35+
// Initialize g as null in case of using g later e.g. sigaction in cgo_sigaction.go
36+
MOVD ZR, g
3337

3438
MOVD R0, _rt0_arm64_linux_lib_argc<>(SB)
3539
MOVD R1, _rt0_arm64_linux_lib_argv<>(SB)
@@ -74,6 +78,7 @@ restore:
7478
FMOVD 136(RSP), F13
7579
FMOVD 144(RSP), F14
7680
FMOVD 152(RSP), F15
81+
MOVD 160(RSP), g
7782
RET
7883

7984
TEXT _rt0_arm64_linux_lib_go(SB),NOSPLIT,$0

src/runtime/sigaction.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build linux,!amd64 freebsd,!amd64
5+
// +build linux,!amd64,!arm64 freebsd,!amd64
66

77
package runtime
88

src/runtime/sys_linux_arm64.s

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,16 @@ TEXT runtime·rt_sigaction(SB),NOSPLIT|NOFRAME,$0-36
292292
MOVW R0, ret+32(FP)
293293
RET
294294

295+
// Call the function stored in _cgo_sigaction using the GCC calling convention.
296+
TEXT runtime·callCgoSigaction(SB),NOSPLIT,$0
297+
MOVD sig+0(FP), R0
298+
MOVD new+8(FP), R1
299+
MOVD old+16(FP), R2
300+
MOVD _cgo_sigaction(SB), R3
301+
BL R3
302+
MOVW R0, ret+24(FP)
303+
RET
304+
295305
TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
296306
MOVW sig+8(FP), R0
297307
MOVD info+16(FP), R1
@@ -320,7 +330,7 @@ TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
320330
MOVD $runtime·sigtramp(SB), R3
321331
B (R3)
322332

323-
TEXT runtime·mmap(SB),NOSPLIT|NOFRAME,$0
333+
TEXT runtime·sysMmap(SB),NOSPLIT|NOFRAME,$0
324334
MOVD addr+0(FP), R0
325335
MOVD n+8(FP), R1
326336
MOVW prot+16(FP), R2
@@ -341,7 +351,21 @@ ok:
341351
MOVD $0, err+40(FP)
342352
RET
343353

344-
TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0
354+
// Call the function stored in _cgo_mmap using the GCC calling convention.
355+
// This must be called on the system stack.
356+
TEXT runtime·callCgoMmap(SB),NOSPLIT,$0
357+
MOVD addr+0(FP), R0
358+
MOVD n+8(FP), R1
359+
MOVW prot+16(FP), R2
360+
MOVW flags+20(FP), R3
361+
MOVW fd+24(FP), R4
362+
MOVW off+28(FP), R5
363+
MOVD _cgo_mmap(SB), R9
364+
BL R9
365+
MOVD R0, ret+32(FP)
366+
RET
367+
368+
TEXT runtime·sysMunmap(SB),NOSPLIT|NOFRAME,$0
345369
MOVD addr+0(FP), R0
346370
MOVD n+8(FP), R1
347371
MOVD $SYS_munmap, R8
@@ -352,6 +376,15 @@ TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0
352376
cool:
353377
RET
354378

379+
// Call the function stored in _cgo_munmap using the GCC calling convention.
380+
// This must be called on the system stack.
381+
TEXT runtime·callCgoMunmap(SB),NOSPLIT,$0
382+
MOVD addr+0(FP), R0
383+
MOVD n+8(FP), R1
384+
MOVD _cgo_munmap(SB), R9
385+
BL R9
386+
RET
387+
355388
TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
356389
MOVD addr+0(FP), R0
357390
MOVD n+8(FP), R1

0 commit comments

Comments
 (0)