mirror of
https://github.com/dart-lang/sdk
synced 2024-09-19 14:32:49 +00:00
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:
parent
8672603473
commit
08edbbd6b4
23
runtime/platform/address_sanitizer.h
Normal file
23
runtime/platform/address_sanitizer.h
Normal 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_
|
23
runtime/platform/memory_sanitizer.h
Normal file
23
runtime/platform/memory_sanitizer.h
Normal 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_
|
|
@ -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',
|
||||
],
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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); \
|
||||
{ \
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue