Commit beaf1073 authored by Guanzhong Chen's avatar Guanzhong Chen Committed by Commit Bot

[wasm] use standard WebAssembly stack trace format

Currently, in wasm-function stack traces, v8 displays the decimal offset
from the start of the function. However, the WebAssembly WebAPI
specification says that it should be a hex offset into the module.

This change makes the stack trace display with hex module offsets, as
well as fixing all the unit tests that depended on the old behaviour.

R=fgm@chromium.org, titzer@chromium.org, yangguo@chromium.org

Bug: v8:9172
Change-Id: I73737a319a42dd665521ab8a4b825199ae11c87f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1646846Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Reviewed-by: 's avatarSimon Zünd <szuend@chromium.org>
Reviewed-by: 's avatarAdam Klein <adamk@chromium.org>
Commit-Queue: Guanzhong Chen <gzchen@google.com>
Cr-Commit-Position: refs/heads/master@{#62103}
parent af927dac
......@@ -769,7 +769,11 @@ void WasmStackFrame::ToString(IncrementalStringBuilder& builder) {
DCHECK(wasm_func_index_ <= kMaxInt);
builder.AppendInt(static_cast<int>(wasm_func_index_));
builder.AppendCString("]:");
builder.AppendInt(GetPosition());
int function_offset = module_object->GetFunctionOffset(wasm_func_index_);
char buffer[16];
SNPrintF(ArrayVector(buffer), "0x%x", function_offset + GetPosition());
builder.AppendCString(buffer);
if (has_name) builder.AppendCString(")");
......
......@@ -18,8 +18,8 @@ end
Getting current stack trace via "new Error().stack".
Error
at v8://test/getStack:1:1
at func (wasm-function[0]:1)
at main (wasm-function[1]:1)
at func (wasm-function[0]:0x21)
at main (wasm-function[1]:0x2f)
at v8://test/runWasm:1:22
exports.main returned.
Finished.
......@@ -12,8 +12,8 @@ Result of evaluate (string):
Error: this is your stack trace:
-- skipped --
at call_debugger (<anonymous>:3:5)
at call_func (wasm-function[1]:1)
at main (wasm-function[2]:3)
at call_func (wasm-function[1]:0x37)
at main (wasm-function[2]:0x3e)
at testFunction (<anonymous>:15:20)
at <anonymous>:1:1
Finished!
wasm-function[0]:5: RuntimeError: wasm exception
RuntimeError: wasm exception
at rethrow0 (wasm-function[0]:5)
at rethrow0 (wasm-function[0]:0x32)
at *%(basename)s:21:18
wasm-function[0]:3: RuntimeError: wasm exception
RuntimeError: wasm exception
at throw0 (wasm-function[0]:3)
at throw0 (wasm-function[0]:0x2e)
at *%(basename)s:17:18
wasm-function[0]:1: RuntimeError: unreachable
RuntimeError: unreachable
at main (wasm-function[0]:1)
at main (wasm-function[0]:0x22)
at *%(basename)s:{NUMBER}:31
wasm-function[0]:1: RuntimeError: unreachable
RuntimeError: unreachable
at test-module.main (wasm-function[0]:1)
at test-module.main (wasm-function[0]:0x22)
at *%(basename)s:{NUMBER}:31
wasm-function[0]:1: RuntimeError: unreachable
RuntimeError: unreachable
at test-module (wasm-function[0]:1)
at test-module (wasm-function[0]:0x22)
at *%(basename)s:{NUMBER}:31
wasm-function[0]:1: RuntimeError: unreachable
RuntimeError: unreachable
at wasm-function[0]:1
at wasm-function[0]:0x22
at *%(basename)s:{NUMBER}:31
wasm-function[0]:5: RuntimeError: divide by zero
RuntimeError: divide by zero
at main (wasm-function[0]:5)
at main (wasm-function[0]:0x26)
at *%(basename)s:{NUMBER}:16
RuntimeError: unreachable
at main (wasm-function[0]:1)
at main (wasm-function[0]:0x22)
at *%(basename)s:{NUMBER}:27
at test/mjsunit/mjsunit.js:*
RuntimeError: unreachable
at main (wasm-function[0]:1)
at main (wasm-function[0]:0x22)
at test/message/wasm-function-name-async.js:{NUMBER}:27
at test/mjsunit/mjsunit.js:*
RuntimeError: unreachable
at test-module.main (wasm-function[0]:1)
at test-module.main (wasm-function[0]:0x22)
at *%(basename)s:{NUMBER}:27
at test/mjsunit/mjsunit.js:*
RuntimeError: unreachable
at test-module.main (wasm-function[0]:1)
at test-module.main (wasm-function[0]:0x22)
at test/message/wasm-module-and-function-name-async.js:{NUMBER}:27
at test/mjsunit/mjsunit.js:*
RuntimeError: unreachable
at test-module (wasm-function[0]:1)
at test-module (wasm-function[0]:0x22)
at *%(basename)s:{NUMBER}:27
at test/mjsunit/mjsunit.js:*
RuntimeError: unreachable
at test-module (wasm-function[0]:1)
at test-module (wasm-function[0]:0x22)
at test/message/wasm-module-name-async.js:{NUMBER}:27
at test/mjsunit/mjsunit.js:*
RuntimeError: unreachable
at wasm-function[0]:1
at wasm-function[0]:0x22
at *%(basename)s:{NUMBER}:27
at test/mjsunit/mjsunit.js:*
RuntimeError: unreachable
at wasm-function[0]:1
at wasm-function[0]:0x22
at test/message/wasm-no-name-async.js:{NUMBER}:27
at test/mjsunit/mjsunit.js:*
......@@ -184,8 +184,8 @@ function redirectToInterpreter(
checkStack(stripPath(e.stack), [
'Error: i=8', // -
/^ at imp \(file:\d+:29\)$/, // -
' at plus_one (wasm-function[1]:6)', // -
' at plus_two (wasm-function[1]:3)', // -
' at plus_one (wasm-function[1]:0x3b)', // -
' at plus_two (wasm-function[1]:0x3e)', // -
/^ at testStackTraceThroughCWasmEntry \(file:\d+:25\)$/, // -
/^ at file:\d+:3$/
]);
......
......@@ -39,7 +39,7 @@ function checkStack(stack, expected_lines) {
checkStack(stripPath(stack), [
'Error: test imported stack', // -
/^ at func \(interpreter.js:\d+:28\)$/, // -
' at main (wasm-function[1]:1)', // -
' at main (wasm-function[1]:0x32)', // -
/^ at testCallImported \(interpreter.js:\d+:22\)$/, // -
/^ at interpreter.js:\d+:3$/
]);
......@@ -103,8 +103,8 @@ function checkStack(stack, expected_lines) {
assertEquals(interpreted_before + 2, %WasmNumInterpretedCalls(instance));
checkStack(stripPath(stack), [
'RuntimeError: unreachable', // -
' at foo (wasm-function[0]:3)', // -
' at main (wasm-function[1]:2)', // -
' at foo (wasm-function[0]:0x27)', // -
' at main (wasm-function[1]:0x2c)', // -
/^ at testTrap \(interpreter.js:\d+:24\)$/, // -
/^ at interpreter.js:\d+:3$/
]);
......@@ -136,7 +136,7 @@ function checkStack(stack, expected_lines) {
checkStack(stripPath(stack), [
'Error: thrown from imported function', // -
/^ at func \(interpreter.js:\d+:11\)$/, // -
' at main (wasm-function[1]:1)', // -
' at main (wasm-function[1]:0x32)', // -
/^ at testThrowFromImport \(interpreter.js:\d+:24\)$/, // -
/^ at interpreter.js:\d+:3$/
]);
......@@ -218,10 +218,10 @@ function checkStack(stack, expected_lines) {
for (var e = 0; e < stacks.length; ++e) {
expected = ['Error: reentrant interpreter test #' + e];
expected.push(/^ at func \(interpreter.js:\d+:17\)$/);
expected.push(' at main (wasm-function[1]:3)');
expected.push(' at main (wasm-function[1]:0x36)');
for (var k = e; k > 0; --k) {
expected.push(/^ at func \(interpreter.js:\d+:33\)$/);
expected.push(' at main (wasm-function[1]:3)');
expected.push(' at main (wasm-function[1]:0x36)');
}
expected.push(
/^ at testReentrantInterpreter \(interpreter.js:\d+:22\)$/);
......@@ -296,8 +296,8 @@ function checkStack(stack, expected_lines) {
if (!(e instanceof TypeError)) throw e;
checkStack(stripPath(e.stack), [
'TypeError: ' + kTrapMsgs[kTrapTypeError], // -
' at direct (wasm-function[1]:1)', // -
' at main (wasm-function[3]:3)', // -
' at direct (wasm-function[1]:0x55)', // -
' at main (wasm-function[3]:0x64)', // -
/^ at testIllegalImports \(interpreter.js:\d+:22\)$/, // -
/^ at interpreter.js:\d+:3$/
]);
......@@ -309,8 +309,8 @@ function checkStack(stack, expected_lines) {
if (!(e instanceof TypeError)) throw e;
checkStack(stripPath(e.stack), [
'TypeError: ' + kTrapMsgs[kTrapTypeError], // -
' at indirect (wasm-function[2]:3)', // -
' at main (wasm-function[3]:3)', // -
' at indirect (wasm-function[2]:0x5c)', // -
' at main (wasm-function[3]:0x64)', // -
/^ at testIllegalImports \(interpreter.js:\d+:22\)$/, // -
/^ at interpreter.js:\d+:3$/
]);
......@@ -358,8 +358,8 @@ function checkStack(stack, expected_lines) {
if (!(e instanceof RangeError)) throw e;
checkStack(stripPath(e.stack), [
'RangeError: Maximum call stack size exceeded',
' at main (wasm-function[0]:0)'
].concat(Array(9).fill(' at main (wasm-function[0]:2)')));
' at main (wasm-function[0]:0x20)'
].concat(Array(9).fill(' at main (wasm-function[0]:0x22)')));
}
})();
......
......@@ -23,7 +23,7 @@ function verifyStack(frames, expected) {
assertContains(exp[4], frames[i].getFileName(), "["+i+"].getFileName()");
var toString;
if (exp[0]) {
toString = "wasm-function[" + exp[2] + "]:" + exp[3];
toString = "wasm-function[" + exp[2] + "]:" + exp[5];
if (exp[1] !== null) toString = exp[1] + " (" + toString + ")";
} else {
toString = exp[4] + ":" + exp[2] + ":";
......@@ -70,7 +70,7 @@ var module = builder.instantiate({mod: {func: STACK}});
var expected_string = 'Error\n' +
// The line numbers below will change as this test gains / loses lines..
' at STACK (stack.js:38:11)\n' + // --
' at main (wasm-function[1]:1)\n' + // --
' at main (wasm-function[1]:0x86)\n' + // --
' at testSimpleStack (stack.js:77:18)\n' + // --
' at stack.js:79:3'; // --
......@@ -88,9 +88,9 @@ Error.prepareStackTrace = function(error, frames) {
module.exports.main();
verifyStack(stack, [
// isWasm function line pos file
// isWasm function line pos file offset
[ false, "STACK", 38, 0, "stack.js"],
[ true, "main", 1, 1, null],
[ true, "main", 1, 1, null, '0x86'],
[ false, "testStackFrames", 88, 0, "stack.js"],
[ false, null, 97, 0, "stack.js"]
]);
......@@ -103,8 +103,8 @@ Error.prepareStackTrace = function(error, frames) {
} catch (e) {
assertContains("unreachable", e.message);
verifyStack(e.stack, [
// isWasm function line pos file
[ true, "exec_unreachable", 2, 1, null],
// isWasm function line pos file offset
[ true, "exec_unreachable", 2, 1, null, '0x8b'],
[ false, "testWasmUnreachable", 101, 0, "stack.js"],
[ false, null, 112, 0, "stack.js"]
]);
......@@ -118,9 +118,9 @@ Error.prepareStackTrace = function(error, frames) {
} catch (e) {
assertContains("out of bounds", e.message);
verifyStack(e.stack, [
// isWasm function line pos file
[ true, null, 3, 3, null],
[ true, "call_mem_out_of_bounds", 4, 1, null],
// isWasm function line pos file offset
[ true, null, 3, 3, null, '0x91'],
[ true, "call_mem_out_of_bounds", 4, 1, null, '0x97'],
[ false, "testWasmMemOutOfBounds", 116, 0, "stack.js"],
[ false, null, 128, 0, "stack.js"]
]);
......@@ -147,11 +147,11 @@ Error.prepareStackTrace = function(error, frames) {
assertEquals("Maximum call stack size exceeded", e.message, "trap reason");
assertTrue(e.stack.length >= 4, "expected at least 4 stack entries");
verifyStack(e.stack.splice(0, 4), [
// isWasm function line pos file
[ true, "recursion", 0, 0, null],
[ true, "recursion", 0, 3, null],
[ true, "recursion", 0, 3, null],
[ true, "recursion", 0, 3, null]
// isWasm function line pos file offset
[ true, "recursion", 0, 0, null, '0x34'],
[ true, "recursion", 0, 3, null, '0x37'],
[ true, "recursion", 0, 3, null, '0x37'],
[ true, "recursion", 0, 3, null, '0x37']
]);
}
})();
......@@ -173,11 +173,12 @@ Error.prepareStackTrace = function(error, frames) {
fail('expected wasm exception');
} catch (e) {
assertEquals('unreachable', e.message, 'trap reason');
let hexOffset = '0x' + (unreachable_pos + 0x25).toString(16);
verifyStack(e.stack, [
// isWasm, function, line, pos, file
[true, 'main', 0, unreachable_pos + 1, null], // -
[false, 'testBigOffset', 172, 0, 'stack.js'], //-
[false, null, 183, 0, 'stack.js']
// isWasm, function, line, pos, file, offset
[true, 'main', 0, unreachable_pos + 1, null, hexOffset], // -
[false, 'testBigOffset', 172, 0, 'stack.js'], //-
[false, null, 184, 0, 'stack.js']
]);
}
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment