mirror of https://github.com/golang/go.git
runtime, runtime/msan: add msan runtime support
These are the runtime support functions for letting Go code interoperate with the C/C++ memory sanitizer. Calls to msanread/msanwrite are now inserted by the compiler with the -msan option. Calls to msanmalloc/msanfree will be from other runtime functions in a subsequent CL. Change-Id: I64fb061b38cc6519153face242eccd291c07d1f2 Reviewed-on: https://go-review.googlesource.com/16162 Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: David Crawshaw <crawshaw@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
a42f668654
commit
5174df9087
|
|
@ -263,8 +263,9 @@ var pkgDeps = map[string][]string{
|
||||||
// that shows up in programs that use cgo.
|
// that shows up in programs that use cgo.
|
||||||
"C": {},
|
"C": {},
|
||||||
|
|
||||||
// Race detector uses cgo.
|
// Race detector/MSan uses cgo.
|
||||||
"runtime/race": {"C"},
|
"runtime/race": {"C"},
|
||||||
|
"runtime/msan": {"C"},
|
||||||
|
|
||||||
// Plan 9 alone needs io/ioutil and os.
|
// Plan 9 alone needs io/ioutil and os.
|
||||||
"os/user": {"L4", "CGO", "io/ioutil", "os", "syscall"},
|
"os/user": {"L4", "CGO", "io/ioutil", "os", "syscall"},
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
// 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 msan
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Public memory sanitizer API.
|
||||||
|
|
||||||
|
func MSanRead(addr unsafe.Pointer, len int) {
|
||||||
|
msanread(addr, uintptr(len))
|
||||||
|
}
|
||||||
|
|
||||||
|
func MSanWrite(addr unsafe.Pointer, len int) {
|
||||||
|
msanwrite(addr, uintptr(len))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private interface for the runtime.
|
||||||
|
const msanenabled = true
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func msanread(addr unsafe.Pointer, sz uintptr)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func msanwrite(addr unsafe.Pointer, sz uintptr)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func msanmalloc(addr unsafe.Pointer, sz uintptr)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func msanfree(addr unsafe.Pointer, sz uintptr)
|
||||||
|
|
||||||
|
// These are called from msan_amd64.s
|
||||||
|
//go:cgo_import_static __msan_read_go
|
||||||
|
//go:cgo_import_static __msan_write_go
|
||||||
|
//go:cgo_import_static __msan_malloc_go
|
||||||
|
//go:cgo_import_static __msan_free_go
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
// 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 msan,linux,amd64
|
||||||
|
|
||||||
|
package msan
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -fsanitize=memory
|
||||||
|
#cgo LDFLAGS: -fsanitize=memory
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sanitizer/msan_interface.h>
|
||||||
|
|
||||||
|
void __msan_read_go(void *addr, uintptr_t sz) {
|
||||||
|
__msan_check_mem_is_initialized(addr, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __msan_write_go(void *addr, uintptr_t sz) {
|
||||||
|
__msan_unpoison(addr, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __msan_malloc_go(void *addr, uintptr_t sz) {
|
||||||
|
__msan_unpoison(addr, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __msan_free_go(void *addr, uintptr_t sz) {
|
||||||
|
__msan_poison(addr, sz);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
// 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 !msan
|
||||||
|
|
||||||
|
// Dummy MSan support API, used when not built with -msan.
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const msanenabled = false
|
||||||
|
|
||||||
|
// Because msanenabled is false, none of these functions should be called.
|
||||||
|
|
||||||
|
func msanread(addr unsafe.Pointer, sz uintptr) { throw("race") }
|
||||||
|
func msanwrite(addr unsafe.Pointer, sz uintptr) { throw("race") }
|
||||||
|
func msanmalloc(addr unsafe.Pointer, sz uintptr) { throw("msan") }
|
||||||
|
func msanfree(addr unsafe.Pointer, sz uintptr) { throw("msan") }
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
// +build msan
|
||||||
|
|
||||||
|
#include "go_asm.h"
|
||||||
|
#include "go_tls.h"
|
||||||
|
#include "funcdata.h"
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// This is like race_amd64.s, but for the msan calls.
|
||||||
|
// See race_amd64.s for detailed comments.
|
||||||
|
|
||||||
|
#ifdef GOOS_windows
|
||||||
|
#define RARG0 CX
|
||||||
|
#define RARG1 DX
|
||||||
|
#define RARG2 R8
|
||||||
|
#define RARG3 R9
|
||||||
|
#else
|
||||||
|
#define RARG0 DI
|
||||||
|
#define RARG1 SI
|
||||||
|
#define RARG2 DX
|
||||||
|
#define RARG3 CX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// func runtime·msanread(addr unsafe.Pointer, sz uintptr)
|
||||||
|
// Called from instrumented code.
|
||||||
|
TEXT runtime·msanread(SB), NOSPLIT, $0-16
|
||||||
|
MOVQ addr+0(FP), RARG0
|
||||||
|
MOVQ size+8(FP), RARG1
|
||||||
|
// void __msan_read_go(void *addr, uintptr_t sz);
|
||||||
|
MOVQ $__msan_read_go(SB), AX
|
||||||
|
JMP msancall<>(SB)
|
||||||
|
|
||||||
|
// func runtime·msanwrite(addr unsafe.Pointer, sz uintptr)
|
||||||
|
// Called from instrumented code.
|
||||||
|
TEXT runtime·msanwrite(SB), NOSPLIT, $0-16
|
||||||
|
MOVQ addr+0(FP), RARG0
|
||||||
|
MOVQ size+8(FP), RARG1
|
||||||
|
// void __msan_write_go(void *addr, uintptr_t sz);
|
||||||
|
MOVQ $__msan_write_go(SB), AX
|
||||||
|
JMP msancall<>(SB)
|
||||||
|
|
||||||
|
// func runtime·msanmalloc(addr unsafe.Pointer, sz uintptr)
|
||||||
|
TEXT runtime·msanmalloc(SB), NOSPLIT, $0-16
|
||||||
|
MOVQ addr+0(FP), RARG0
|
||||||
|
MOVQ size+8(FP), RARG1
|
||||||
|
// void __msan_malloc_go(void *addr, uintptr_t sz);
|
||||||
|
MOVQ $__msan_malloc_go(SB), AX
|
||||||
|
JMP msancall<>(SB)
|
||||||
|
|
||||||
|
// func runtime·msanfree(addr unsafe.Pointer, sz uintptr)
|
||||||
|
TEXT runtime·msanfree(SB), NOSPLIT, $0-16
|
||||||
|
MOVQ addr+0(FP), RARG0
|
||||||
|
MOVQ size+8(FP), RARG1
|
||||||
|
// void __msan_free_go(void *addr, uintptr_t sz);
|
||||||
|
MOVQ $__msan_free_go(SB), AX
|
||||||
|
JMP msancall<>(SB)
|
||||||
|
|
||||||
|
// Switches SP to g0 stack and calls (AX). Arguments already set.
|
||||||
|
TEXT msancall<>(SB), NOSPLIT, $0-0
|
||||||
|
get_tls(R12)
|
||||||
|
MOVQ g(R12), R14
|
||||||
|
MOVQ g_m(R14), R13
|
||||||
|
// Switch to g0 stack.
|
||||||
|
MOVQ SP, R12 // callee-saved, preserved across the CALL
|
||||||
|
MOVQ m_g0(R13), R10
|
||||||
|
CMPQ R10, R14
|
||||||
|
JE call // already on g0
|
||||||
|
MOVQ (g_sched+gobuf_sp)(R10), SP
|
||||||
|
call:
|
||||||
|
ANDQ $~15, SP // alignment for gcc ABI
|
||||||
|
CALL AX
|
||||||
|
MOVQ R12, SP
|
||||||
|
RET
|
||||||
Loading…
Reference in New Issue