*/
void SetCaptureMessage(bool value);
+ /**
+ * There are cases when the raw address of C++ TryCatch object cannot be
+ * used for comparisons with addresses into the JS stack. The cases are:
+ * 1) ARM, ARM64 and MIPS simulators which have separate JS stack.
+ * 2) Address sanitizer allocates local C++ object in the heap when
+ * UseAfterReturn mode is enabled.
+ * This method returns address that can be used for comparisons with
+ * addresses into the JS stack. When neither simulator nor ASAN's
+ * UseAfterReturn is enabled, then the address returned will be the address
+ * of the C++ try catch handler itself.
+ */
+ static void* JSStackComparableAddress(v8::TryCatch* handler) {
+ if (handler == NULL) return NULL;
+ return handler->js_stack_comparable_address_;
+ }
+
private:
// Make it hard to create heap-allocated TryCatch blocks.
TryCatch(const TryCatch&);
void operator delete(void*, size_t);
v8::internal::Isolate* isolate_;
- void* next_;
+ v8::TryCatch* next_;
void* exception_;
void* message_obj_;
void* message_script_;
+ void* js_stack_comparable_address_;
int message_start_pos_;
int message_end_pos_;
bool is_verbose_ : 1;
#include <string.h> // For memcpy, strlen.
#include <cmath> // For isnan.
+#ifdef V8_USE_ADDRESS_SANITIZER
+#include <sanitizer/asan_interface.h>
+#endif // V8_USE_ADDRESS_SANITIZER
#include "../include/v8-debug.h"
#include "../include/v8-profiler.h"
#include "../include/v8-testing.h"
#include "runtime.h"
#include "runtime-profiler.h"
#include "scanner-character-streams.h"
+#include "simulator.h"
#include "snapshot.h"
#include "unicode-inl.h"
#include "utils/random-number-generator.h"
v8::TryCatch::TryCatch()
: isolate_(i::Isolate::Current()),
- next_(isolate_->try_catch_handler_address()),
+ next_(isolate_->try_catch_handler()),
is_verbose_(false),
can_continue_(true),
capture_message_(true),
rethrow_(false),
has_terminated_(false) {
Reset();
+ js_stack_comparable_address_ = this;
+#ifdef V8_USE_ADDRESS_SANITIZER
+ void* asan_fake_stack_handle = __asan_get_current_fake_stack();
+ if (asan_fake_stack_handle != NULL) {
+ js_stack_comparable_address_ = __asan_addr_is_in_fake_stack(
+ asan_fake_stack_handle, js_stack_comparable_address_, NULL, NULL);
+ CHECK(js_stack_comparable_address_ != NULL);
+ }
+#endif
+ // Special handling for simulators which have a separate JS stack.
+ js_stack_comparable_address_ = reinterpret_cast<void*>(
+ v8::internal::SimulatorStack::RegisterCTryCatch(
+ reinterpret_cast<uintptr_t>(js_stack_comparable_address_)));
isolate_->RegisterTryCatchHandler(this);
}
isolate_->RestorePendingMessageFromTryCatch(this);
}
isolate_->UnregisterTryCatchHandler(this);
+ v8::internal::SimulatorStack::UnregisterCTryCatch();
reinterpret_cast<Isolate*>(isolate_)->ThrowException(exc);
ASSERT(!isolate_->thread_local_top()->rethrowing_message_);
} else {
isolate_->UnregisterTryCatchHandler(this);
+ v8::internal::SimulatorStack::UnregisterCTryCatch();
}
}
(FUNCTION_CAST<arm_regexp_matcher>(entry)( \
p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8))
-#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
- reinterpret_cast<TryCatch*>(try_catch_address)
-
// The stack limit beyond which we will throw stack overflow errors in
// generated code. Because generated code on arm uses the C stack, we
// just use the C stack limit.
Simulator::current(Isolate::Current())->Call( \
entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8)
-#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
- try_catch_address == NULL ? \
- NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
-
// The simulator has its own stack. Thus it has a different stack limit from
// the C-based native code. Setting the c_limit to indicate a very small
(FUNCTION_CAST<arm64_regexp_matcher>(entry)( \
p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8))
-#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
- reinterpret_cast<TryCatch*>(try_catch_address)
-
// Running without a simulator there is nothing to do.
class SimulatorStack : public v8::internal::AllStatic {
public:
entry, \
p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8)
-#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
- try_catch_address == NULL ? \
- NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
-
// The simulator has its own stack. Thus it has a different stack limit from
// the C-based native code.
#define MUST_USE_RESULT V8_WARN_UNUSED_RESULT
-// Define DISABLE_ASAN macros.
+// Define V8_USE_ADDRESS_SANITIZER macros.
#if defined(__has_feature)
#if __has_feature(address_sanitizer)
-#define DISABLE_ASAN __attribute__((no_sanitize_address))
+#define V8_USE_ADDRESS_SANITIZER 1
#endif
#endif
-
-#ifndef DISABLE_ASAN
+// Define DISABLE_ASAN macros.
+#ifdef V8_USE_ADDRESS_SANITIZER
+#define DISABLE_ASAN __attribute__((no_sanitize_address))
+#else
#define DISABLE_ASAN
#endif
(FUNCTION_CAST<regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7, p8))
-#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
- (reinterpret_cast<TryCatch*>(try_catch_address))
-
// The stack limit beyond which we will throw stack overflow errors in
// generated code. Because generated code on ia32 uses the C stack, we
// just use the C stack limit.
js_entry_sp_ = NULL;
external_callback_scope_ = NULL;
current_vm_state_ = EXTERNAL;
- try_catch_handler_address_ = NULL;
+ try_catch_handler_ = NULL;
context_ = NULL;
thread_id_ = ThreadId::Invalid();
external_caught_exception_ = false;
}
-v8::TryCatch* ThreadLocalTop::TryCatchHandler() {
- return TRY_CATCH_FROM_ADDRESS(try_catch_handler_address());
-}
-
-
Thread::LocalStorageKey Isolate::isolate_key_;
Thread::LocalStorageKey Isolate::thread_id_key_;
Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
v->VisitPointer(BitCast<Object**>(&(thread->context_)));
v->VisitPointer(&thread->scheduled_exception_);
- for (v8::TryCatch* block = thread->TryCatchHandler();
+ for (v8::TryCatch* block = thread->try_catch_handler();
block != NULL;
- block = TRY_CATCH_FROM_ADDRESS(block->next_)) {
+ block = block->next_) {
v->VisitPointer(BitCast<Object**>(&(block->exception_)));
v->VisitPointer(BitCast<Object**>(&(block->message_obj_)));
v->VisitPointer(BitCast<Object**>(&(block->message_script_)));
void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) {
- // The ARM simulator has a separate JS stack. We therefore register
- // the C++ try catch handler with the simulator and get back an
- // address that can be used for comparisons with addresses into the
- // JS stack. When running without the simulator, the address
- // returned will be the address of the C++ try catch handler itself.
- Address address = reinterpret_cast<Address>(
- SimulatorStack::RegisterCTryCatch(reinterpret_cast<uintptr_t>(that)));
- thread_local_top()->set_try_catch_handler_address(address);
+ thread_local_top()->set_try_catch_handler(that);
}
void Isolate::UnregisterTryCatchHandler(v8::TryCatch* that) {
- ASSERT(thread_local_top()->TryCatchHandler() == that);
- thread_local_top()->set_try_catch_handler_address(
- reinterpret_cast<Address>(that->next_));
+ ASSERT(thread_local_top()->try_catch_handler() == that);
+ thread_local_top()->set_try_catch_handler(that->next_);
thread_local_top()->catcher_ = NULL;
- SimulatorStack::UnregisterCTryCatch();
}
// Get the top C++ try catch handler or NULL if none are registered.
//
- // This method is not guarenteed to return an address that can be
+ // This method is not guaranteed to return an address that can be
// used for comparison with addresses into the JS stack. If such an
// address is needed, use try_catch_handler_address.
- v8::TryCatch* TryCatchHandler();
+ FIELD_ACCESSOR(v8::TryCatch*, try_catch_handler)
// Get the address of the top C++ try catch handler or NULL if
// none are registered.
// stack, try_catch_handler_address returns a JS stack address that
// corresponds to the place on the JS stack where the C++ handler
// would have been if the stack were not separate.
- FIELD_ACCESSOR(Address, try_catch_handler_address)
+ Address try_catch_handler_address() {
+ return reinterpret_cast<Address>(
+ v8::TryCatch::JSStackComparableAddress(try_catch_handler()));
+ }
void Free() {
ASSERT(!has_pending_message_);
ASSERT(!external_caught_exception_);
- ASSERT(try_catch_handler_address_ == NULL);
+ ASSERT(try_catch_handler_ == NULL);
}
Isolate* isolate_;
private:
void InitializeInternal();
- Address try_catch_handler_address_;
+ v8::TryCatch* try_catch_handler_;
};
thread_local_top_.pending_message_script_ = heap_.the_hole_value();
}
v8::TryCatch* try_catch_handler() {
- return thread_local_top_.TryCatchHandler();
+ return thread_local_top_.try_catch_handler();
}
Address try_catch_handler_address() {
return thread_local_top_.try_catch_handler_address();
(FUNCTION_CAST<mips_regexp_matcher>(entry)( \
p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8))
-#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
- reinterpret_cast<TryCatch*>(try_catch_address)
-
// The stack limit beyond which we will throw stack overflow errors in
// generated code. Because generated code on mips uses the C stack, we
// just use the C stack limit.
Simulator::current(Isolate::Current())->Call( \
entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8)
-#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
- try_catch_address == NULL ? \
- NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
-
// The simulator has its own stack. Thus it has a different stack limit from
// the C-based native code. Setting the c_limit to indicate a very small
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
(FUNCTION_CAST<regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7, p8))
-#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
- (reinterpret_cast<TryCatch*>(try_catch_address))
-
// The stack limit beyond which we will throw stack overflow errors in
// generated code. Because generated code on x64 uses the C stack, we
// just use the C stack limit.
namespace v8 {
namespace internal {
-#if defined(__has_feature)
- #if __has_feature(address_sanitizer)
- #define V8_USE_ADDRESS_SANITIZER
- #endif
-#endif
class Segment;
class Isolate;