LCOV - code coverage report
Current view: top level - test/cctest/wasm - test-wasm-trap-position.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 51 51 100.0 %
Date: 2019-01-20 Functions: 12 12 100.0 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/api-inl.h"
       6             : #include "src/assembler-inl.h"
       7             : #include "src/trap-handler/trap-handler.h"
       8             : #include "test/cctest/cctest.h"
       9             : #include "test/cctest/compiler/value-helper.h"
      10             : #include "test/cctest/wasm/wasm-run-utils.h"
      11             : #include "test/common/wasm/test-signatures.h"
      12             : #include "test/common/wasm/wasm-macro-gen.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : namespace wasm {
      17             : namespace test_wasm_trap_position {
      18             : 
      19             : using v8::Local;
      20             : using v8::Utils;
      21             : 
      22             : namespace {
      23             : 
      24             : #define CHECK_CSTREQ(exp, found)                                           \
      25             :   do {                                                                     \
      26             :     const char* exp_ = (exp);                                              \
      27             :     const char* found_ = (found);                                          \
      28             :     DCHECK_NOT_NULL(exp);                                                  \
      29             :     if (V8_UNLIKELY(found_ == nullptr || strcmp(exp_, found_) != 0)) {     \
      30             :       V8_Fatal(__FILE__, __LINE__,                                         \
      31             :                "Check failed: (%s) != (%s) ('%s' vs '%s').", #exp, #found, \
      32             :                exp_, found_ ? found_ : "<null>");                          \
      33             :     }                                                                      \
      34             :   } while (false)
      35             : 
      36             : struct ExceptionInfo {
      37             :   const char* func_name;
      38             :   int line_nr;
      39             :   int column;
      40             : };
      41             : 
      42             : template <int N>
      43          30 : void CheckExceptionInfos(v8::internal::Isolate* i_isolate, Handle<Object> exc,
      44             :                          const ExceptionInfo (&excInfos)[N]) {
      45             :   // Check that it's indeed an Error object.
      46          60 :   CHECK(exc->IsJSError());
      47             :   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(i_isolate);
      48             : 
      49          60 :   exc->Print();
      50             :   // Extract stack frame from the exception.
      51          30 :   Local<v8::Value> localExc = Utils::ToLocal(exc);
      52          30 :   v8::Local<v8::StackTrace> stack = v8::Exception::GetStackTrace(localExc);
      53          30 :   CHECK(!stack.IsEmpty());
      54          30 :   CHECK_EQ(N, stack->GetFrameCount());
      55             : 
      56          75 :   for (int frameNr = 0; frameNr < N; ++frameNr) {
      57          75 :     v8::Local<v8::StackFrame> frame = stack->GetFrame(v8_isolate, frameNr);
      58         150 :     v8::String::Utf8Value funName(v8_isolate, frame->GetFunctionName());
      59          75 :     CHECK_CSTREQ(excInfos[frameNr].func_name, *funName);
      60          75 :     CHECK_EQ(excInfos[frameNr].line_nr, frame->GetLineNumber());
      61          75 :     CHECK_EQ(excInfos[frameNr].column, frame->GetColumn());
      62             :   }
      63          30 : }
      64             : 
      65             : #undef CHECK_CSTREQ
      66             : 
      67             : }  // namespace
      68             : 
      69             : // Trigger a trap for executing unreachable.
      70       28367 : WASM_EXEC_TEST(Unreachable) {
      71             :   // Create a WasmRunner with stack checks and traps enabled.
      72          15 :   WasmRunner<void> r(execution_tier, nullptr, "main", kRuntimeExceptionSupport);
      73          15 :   TestSignatures sigs;
      74             : 
      75          15 :   BUILD(r, WASM_UNREACHABLE);
      76          15 :   uint32_t wasm_index = r.function()->func_index;
      77             : 
      78          15 :   Handle<JSFunction> js_wasm_wrapper = r.builder().WrapCode(wasm_index);
      79             : 
      80             :   Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast(
      81             :       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
      82          15 :           CompileRun("(function callFn(fn) { fn(); })"))));
      83             : 
      84             :   Isolate* isolate = js_wasm_wrapper->GetIsolate();
      85             :   isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
      86          15 :                                                      v8::StackTrace::kOverview);
      87          30 :   Handle<Object> global(isolate->context()->global_object(), isolate);
      88          15 :   MaybeHandle<Object> maybe_exc;
      89             :   Handle<Object> args[] = {js_wasm_wrapper};
      90             :   MaybeHandle<Object> returnObjMaybe =
      91             :       Execution::TryCall(isolate, js_trampoline, global, 1, args,
      92          15 :                          Execution::MessageHandling::kReport, &maybe_exc);
      93          15 :   CHECK(returnObjMaybe.is_null());
      94             : 
      95             :   // Line and column are 1-based, so add 1 for the expected wasm output.
      96             :   ExceptionInfo expected_exceptions[] = {
      97          15 :       {"main", static_cast<int>(wasm_index) + 1, 2},  // --
      98             :       {"callFn", 1, 24}                               // --
      99          30 :   };
     100             :   CheckExceptionInfos(isolate, maybe_exc.ToHandleChecked(),
     101          15 :                       expected_exceptions);
     102          15 : }
     103             : 
     104             : // Trigger a trap for loading from out-of-bounds.
     105       28367 : WASM_EXEC_TEST(IllegalLoad) {
     106          15 :   WasmRunner<void> r(execution_tier, nullptr, "main", kRuntimeExceptionSupport);
     107          15 :   TestSignatures sigs;
     108             : 
     109          15 :   r.builder().AddMemory(0L);
     110             : 
     111          15 :   BUILD(r, WASM_IF(WASM_ONE, WASM_SEQ(WASM_LOAD_MEM(MachineType::Int32(),
     112             :                                                     WASM_I32V_1(-3)),
     113             :                                       WASM_DROP)));
     114          15 :   uint32_t wasm_index_1 = r.function()->func_index;
     115             : 
     116          30 :   WasmFunctionCompiler& f2 = r.NewFunction<void>("call_main");
     117             :   // Insert a NOP such that the position of the call is not one.
     118          15 :   BUILD(f2, WASM_NOP, WASM_CALL_FUNCTION0(wasm_index_1));
     119             :   uint32_t wasm_index_2 = f2.function_index();
     120             : 
     121          15 :   Handle<JSFunction> js_wasm_wrapper = r.builder().WrapCode(wasm_index_2);
     122             : 
     123             :   Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast(
     124             :       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
     125          15 :           CompileRun("(function callFn(fn) { fn(); })"))));
     126             : 
     127             :   Isolate* isolate = js_wasm_wrapper->GetIsolate();
     128             :   isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
     129          15 :                                                      v8::StackTrace::kOverview);
     130          30 :   Handle<Object> global(isolate->context()->global_object(), isolate);
     131          15 :   MaybeHandle<Object> maybe_exc;
     132             :   Handle<Object> args[] = {js_wasm_wrapper};
     133             :   MaybeHandle<Object> returnObjMaybe =
     134             :       Execution::TryCall(isolate, js_trampoline, global, 1, args,
     135          15 :                          Execution::MessageHandling::kReport, &maybe_exc);
     136          15 :   CHECK(returnObjMaybe.is_null());
     137             : 
     138             :   // Line and column are 1-based, so add 1 for the expected wasm output.
     139             :   ExceptionInfo expected_exceptions[] = {
     140          15 :       {"main", static_cast<int>(wasm_index_1) + 1, 8},       // --
     141          15 :       {"call_main", static_cast<int>(wasm_index_2) + 1, 3},  // --
     142             :       {"callFn", 1, 24}                                      // --
     143          45 :   };
     144             :   CheckExceptionInfos(isolate, maybe_exc.ToHandleChecked(),
     145          15 :                       expected_exceptions);
     146          15 : }
     147             : 
     148             : }  // namespace test_wasm_trap_position
     149             : }  // namespace wasm
     150             : }  // namespace internal
     151       85011 : }  // namespace v8

Generated by: LCOV version 1.10