// Copyright 2020 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Flags: --expose-wasm --wasm-expose-debug-eval utils.load('test/inspector/wasm-inspector-test.js'); const {session, contextGroup, Protocol} = InspectorTest.start('Tests wasm debug-evaluate'); function printFailure(message) { if (!message.result) { InspectorTest.logMessage(message); } return message; } async function getWasmScript() { while (true) { const script = await Protocol.Debugger.onceScriptParsed(); if (script.params.url.startsWith('wasm://')) return script.params; } } async function handleDebuggerPaused(data, messageObject) { const topFrameId = messageObject.params.callFrames[0].callFrameId; const params = {callFrameId: topFrameId, evaluator: data}; try { const evalResult = await Protocol.Debugger.executeWasmEvaluator(params); InspectorTest.log('Result: ' + evalResult.result.result.value); } catch (err) { InspectorTest.log( 'Eval failed: ' + err + '\nGot: ' + JSON.stringify(evalResult)); } await Protocol.Debugger.resume(); } async function runTest(testName, breakLine, debuggeeBytes, snippetBytes) { try { await Protocol.Debugger.onPaused( handleDebuggerPaused.bind(null, snippetBytes)); InspectorTest.log('Test: ' + testName); const scriptListener = getWasmScript(); await WasmInspectorTest.instantiate(debuggeeBytes); const script = await scriptListener; const msg = await Protocol.Debugger.setBreakpoint({ 'location': { 'scriptId': script.scriptId, 'lineNumber': 0, 'columnNumber': breakLine } }); printFailure(msg); const eval = await Protocol.Runtime.evaluate( {'expression': 'instance.exports.main()'}); InspectorTest.log( 'Expected: ' + String.fromCharCode(eval.result.result.value)); InspectorTest.log('Finished!'); } catch (err) { InspectorTest.log(err.message); } } // copied from v8 function encode64(data) { const BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; const PAD = '='; var ret = ''; var leftchar = 0; var leftbits = 0; for (var i = 0; i < data.length; i++) { leftchar = (leftchar << 8) | data[i]; leftbits += 8; while (leftbits >= 6) { const curr = (leftchar >> (leftbits - 6)) & 0x3f; leftbits -= 6; ret += BASE[curr]; } } if (leftbits == 2) { ret += BASE[(leftchar & 3) << 4]; ret += PAD + PAD; } else if (leftbits == 4) { ret += BASE[(leftchar & 0xf) << 2]; ret += PAD; } return ret; } (async () => { try { await Protocol.Debugger.enable(); await (async function TestGetMemory() { const debuggee_builder = new WasmModuleBuilder(); debuggee_builder.addMemory(256, 256); const mainFunc = debuggee_builder.addFunction('main', kSig_i_v) .addBody([ // clang-format off kExprI32Const, 32, kExprI32Const, 50, kExprI32StoreMem, 0, 0, kExprI32Const, 32, kExprI32LoadMem, 0, 0, kExprReturn // clang-format on ]) .exportAs('main'); const snippet_builder = new WasmModuleBuilder(); snippet_builder.addMemory(1, 1); const getMemoryIdx = snippet_builder.addImport( 'env', '__getMemory', makeSig([kWasmI32, kWasmI32, kWasmI32], [])); const heapBase = 32; // Just pick some position in memory snippet_builder.addFunction('wasm_format', kSig_i_v) .addBody([ // clang-format off // __getMemory(32, 4, heapBase) kExprI32Const, 32, kExprI32Const, 4, kExprI32Const, heapBase, kExprCallFunction, getMemoryIdx, // return heapBase kExprI32Const, heapBase, kExprReturn // clang-format on ]) .exportAs('wasm_format'); const debuggeeModule = debuggee_builder.toArray(); await runTest( 'TestGetMemory', mainFunc.body_offset + 9, debuggeeModule, encode64(snippet_builder.toArray())); })(); } catch (err) { InspectorTest.log(err) } InspectorTest.completeTest(); })();