MemorySanitizer support.

Enables building (including generating snapshot) and running simple scripts under MemorySanitizer.
Not all tests pass yet.

R=asiva@google.com

Review URL: https://codereview.chromium.org//816123002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@42561 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
koda@google.com 2014-12-23 01:07:58 +00:00
parent 8672603473
commit 08edbbd6b4
10 changed files with 83 additions and 19 deletions

View file

@ -0,0 +1,23 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef PLATFORM_ADDRESS_SANITIZER_H_
#define PLATFORM_ADDRESS_SANITIZER_H_
#include "platform/globals.h"
// Allow the use of ASan (AddressSanitizer). This is needed as ASan needs to be
// told about areas where the VM does the equivalent of a long-jump.
#if defined(__has_feature)
#if __has_feature(address_sanitizer)
extern "C" void __asan_unpoison_memory_region(void *, size_t);
#define ASAN_UNPOISON(ptr, len) __asan_unpoison_memory_region(ptr, len)
#else // __has_feature(address_sanitizer)
#define ASAN_UNPOISON(ptr, len) do {} while (false && (ptr) == 0 && (len) == 0)
#endif // __has_feature(address_sanitizer)
#else // defined(__has_feature)
#define ASAN_UNPOISON(ptr, len) do {} while (false && (ptr) == 0 && (len) == 0)
#endif // defined(__has_feature)
#endif // PLATFORM_ADDRESS_SANITIZER_H_

View file

@ -0,0 +1,23 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef PLATFORM_MEMORY_SANITIZER_H_
#define PLATFORM_MEMORY_SANITIZER_H_
#include "platform/globals.h"
// Allow the use of Msan (MemorySanitizer). This is needed as Msan needs to be
// told about areas that are initialized by generated code.
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
extern "C" void __msan_unpoison(void *, size_t);
#define MSAN_UNPOISON(ptr, len) __msan_unpoison(ptr, len)
#else // __has_feature(memory_sanitizer)
#define MSAN_UNPOISON(ptr, len) do {} while (false && (ptr) == 0 && (len) == 0)
#endif // __has_feature(memory_sanitizer)
#else // defined(__has_feature)
#define MSAN_UNPOISON(ptr, len) do {} while (false && (ptr) == 0 && (len) == 0)
#endif // defined(__has_feature)
#endif // PLATFORM_MEMORY_SANITIZER_H_

View file

@ -5,14 +5,16 @@
# This file contains headers shared between the vm and bin components.
{
'sources': [
'address_sanitizer.h',
'assert.h',
'c99_support_win.h',
'floating_point.h',
'floating_point_win.h',
'globals.h',
'hashmap.h',
'inttypes_support_win.h',
'json.h',
'floating_point.h',
'floating_point_win.h',
'memory_sanitizer.h',
'utils.h',
],
}

View file

@ -4,6 +4,8 @@
#include "vm/exceptions.h"
#include "platform/address_sanitizer.h"
#include "vm/dart_api_impl.h"
#include "vm/dart_entry.h"
#include "vm/debugger.h"
@ -15,19 +17,6 @@
#include "vm/symbols.h"
#include "vm/tags.h"
// Allow the use of ASan (AddressSanitizer). This is needed as ASan needs to be
// told about areas where the VM does the equivalent of a long-jump.
#if defined(__has_feature)
#if __has_feature(address_sanitizer)
extern "C" void __asan_unpoison_memory_region(void *, size_t);
#else // __has_feature(address_sanitizer)
void __asan_unpoison_memory_region(void* ignore1, size_t ignore2) {}
#endif // __has_feature(address_sanitizer)
#else // defined(__has_feature)
void __asan_unpoison_memory_region(void* ignore1, size_t ignore2) {}
#endif // defined(__has_feature)
namespace dart {
DEFINE_FLAG(bool, print_stacktrace_at_throw, false,
@ -310,8 +299,8 @@ static void JumpToExceptionHandler(Isolate* isolate,
// Unpoison the stack before we tear it down in the generated stub code.
uword current_sp = reinterpret_cast<uword>(&program_counter) - 1024;
__asan_unpoison_memory_region(reinterpret_cast<void*>(current_sp),
stack_pointer - current_sp);
ASAN_UNPOISON(reinterpret_cast<void*>(current_sp),
stack_pointer - current_sp);
func(program_counter, stack_pointer, frame_pointer,
raw_exception, raw_stacktrace, isolate);

View file

@ -6,6 +6,7 @@
#define VM_NATIVE_ARGUMENTS_H_
#include "platform/assert.h"
#include "platform/memory_sanitizer.h"
#include "vm/globals.h"
#include "vm/handles_impl.h"
#include "vm/simulator.h"
@ -89,7 +90,10 @@ class NativeArguments {
RawObject* ArgAt(int index) const {
ASSERT((index >= 0) && (index < ArgCount()));
return (*argv_)[-index];
RawObject** arg_ptr = &((*argv_)[-index]);
// Tell MemorySanitizer the RawObject* was initialized (by generated code).
MSAN_UNPOISON(arg_ptr, kWordSize);
return *arg_ptr;
}
int NativeArgCount() const {

View file

@ -86,6 +86,8 @@ void NativeEntry::NativeCallWrapper(Dart_NativeArguments args,
CHECK_STACK_ALIGNMENT;
VERIFY_ON_TRANSITION;
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
/* Tell MemorySanitizer 'arguments' is initialized by generated code. */
MSAN_UNPOISON(arguments, sizeof(*arguments));
Isolate* isolate = arguments->isolate();
ApiState* state = isolate->api_state();

View file

@ -5,6 +5,8 @@
#ifndef VM_NATIVE_ENTRY_H_
#define VM_NATIVE_ENTRY_H_
#include "platform/memory_sanitizer.h"
#include "vm/allocation.h"
#include "vm/assembler.h"
#include "vm/code_generator.h"
@ -42,6 +44,8 @@ typedef void (*NativeFunction)(NativeArguments* arguments);
CHECK_STACK_ALIGNMENT; \
VERIFY_ON_TRANSITION; \
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); \
/* Tell MemorySanitizer 'arguments' is initialized by generated code. */ \
MSAN_UNPOISON(arguments, sizeof(*arguments)); \
ASSERT(arguments->NativeArgCount() == argument_count); \
TRACE_NATIVE_CALL("%s", ""#name); \
{ \

View file

@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "platform/memory_sanitizer.h"
#include "platform/utils.h"
#include "vm/allocation.h"
@ -1934,7 +1935,10 @@ class ProfilerNativeStackWalker : public ValueObject {
uword* CallerFP(uword* fp) const {
ASSERT(fp != NULL);
return reinterpret_cast<uword*>(*(fp + kSavedCallerFpSlotFromFp));
uword* caller_fp_ptr = fp + kSavedCallerFpSlotFromFp;
// This may actually be uninitialized, by design (see class comment above).
MSAN_UNPOISON(caller_fp_ptr, kWordSize);
return reinterpret_cast<uword*>(*caller_fp_ptr);
}
bool ValidFramePointer(uword* fp) const {

View file

@ -524,6 +524,8 @@ void Scavenger::IterateStoreBuffers(Isolate* isolate,
StoreBufferBlock* pending = isolate->store_buffer()->Blocks();
while (pending != NULL) {
StoreBufferBlock* next = pending->next();
// Generated code appends to store buffers; tell MemorySanitizer.
MSAN_UNPOISON(pending, sizeof(*pending));
intptr_t count = pending->Count();
for (intptr_t i = 0; i < count; i++) {
RawObject* raw_object = pending->At(i);

View file

@ -4,6 +4,7 @@
#include "vm/stack_frame.h"
#include "platform/memory_sanitizer.h"
#include "vm/assembler.h"
#include "vm/deopt_instructions.h"
#include "vm/isolate.h"
@ -278,6 +279,15 @@ void StackFrameIterator::SetupNextExitFrameData() {
}
// Tell MemorySanitizer that generated code initializes part of the stack.
// TODO(koda): Limit to frames that are actually written by generated code.
static void UnpoisonStack(Isolate* isolate, uword fp) {
ASSERT(fp != 0);
uword size = isolate->GetSpecifiedStackSize();
MSAN_UNPOISON(reinterpret_cast<void*>(fp - size), 2 * size);
}
StackFrameIterator::StackFrameIterator(bool validate, Isolate* isolate)
: validate_(validate),
entry_(isolate),
@ -340,6 +350,7 @@ StackFrame* StackFrameIterator::NextFrame() {
if (!HasNextFrame()) {
return NULL;
}
UnpoisonStack(isolate_, frames_.fp_);
if (frames_.pc_ == 0) {
// Iteration starts from an exit frame given by its fp.
current_frame_ = NextExitFrame();