forked from mirrors/gecko-dev
This used to be a node package. Let's make it become regular commonjs devtools modules. This will make it trivial to migrate this to ES Modules. Also possibly make this code become the unique layer in m-c on top of the source-map package. We no longer use webpack to build the two bundles (index.js and worker.js), instead, we are using the toolkit worker loader (require.js) in order to load all this code without any build step. As this is no longer a node package, I removed node-specific modules (assertRoot/wasmAsset) and simplify the definition of wasm file URIs as they are now fixed. Also moving the debugger to load internal "devtools/client/shared/source-map/source-map.js" module in jest as running the Web Worker instantiated by source-map/index.js is too complex. Differential Revision: https://phabricator.services.mozilla.com/D159115
260 lines
5.8 KiB
JavaScript
260 lines
5.8 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
|
|
|
/* eslint camelcase: 0*/
|
|
/* eslint-disable no-inline-comments */
|
|
|
|
"use strict";
|
|
|
|
class Value {
|
|
val;
|
|
|
|
constructor(val) {
|
|
this.val = val;
|
|
}
|
|
toString() {
|
|
return `${this.val}`;
|
|
}
|
|
}
|
|
|
|
const Int32Formatter = {
|
|
fromAddr(addr) {
|
|
return `(new DataView(memory0.buffer).getInt32(${addr}, true))`;
|
|
},
|
|
fromValue(value) {
|
|
return `${value.val}`;
|
|
},
|
|
};
|
|
|
|
const Uint32Formatter = {
|
|
fromAddr(addr) {
|
|
return `(new DataView(memory0.buffer).getUint32(${addr}, true))`;
|
|
},
|
|
fromValue(value) {
|
|
return `(${value.val} >>> 0)`;
|
|
},
|
|
};
|
|
|
|
function createPieceFormatter(bytes) {
|
|
let getter;
|
|
switch (bytes) {
|
|
case 0:
|
|
case 1:
|
|
getter = "getUint8";
|
|
break;
|
|
case 2:
|
|
getter = "getUint16";
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
default:
|
|
// FIXME 64-bit
|
|
getter = "getUint32";
|
|
break;
|
|
}
|
|
const mask = (1 << (8 * bytes)) - 1;
|
|
return {
|
|
fromAddr(addr) {
|
|
return `(new DataView(memory0.buffer).${getter}(${addr}, true))`;
|
|
},
|
|
fromValue(value) {
|
|
return `((${value.val} & ${mask}) >>> 0)`;
|
|
},
|
|
};
|
|
}
|
|
|
|
// eslint-disable-next-line complexity
|
|
function toJS(buf, typeFormatter, frame_base = "fp()") {
|
|
const readU8 = function() {
|
|
return buf[i++];
|
|
};
|
|
const readS8 = function() {
|
|
return (readU8() << 24) >> 24;
|
|
};
|
|
const readU16 = function() {
|
|
const w = buf[i] | (buf[i + 1] << 8);
|
|
i += 2;
|
|
return w;
|
|
};
|
|
const readS16 = function() {
|
|
return (readU16() << 16) >> 16;
|
|
};
|
|
const readS32 = function() {
|
|
const w =
|
|
buf[i] | (buf[i + 1] << 8) | (buf[i + 2] << 16) | (buf[i + 3] << 24);
|
|
i += 4;
|
|
return w;
|
|
};
|
|
const readU32 = function() {
|
|
return readS32() >>> 0;
|
|
};
|
|
const readU = function() {
|
|
let n = 0,
|
|
shift = 0,
|
|
b;
|
|
while ((b = readU8()) & 0x80) {
|
|
n |= (b & 0x7f) << shift;
|
|
shift += 7;
|
|
}
|
|
return n | (b << shift);
|
|
};
|
|
const readS = function() {
|
|
let n = 0,
|
|
shift = 0,
|
|
b;
|
|
while ((b = readU8()) & 0x80) {
|
|
n |= (b & 0x7f) << shift;
|
|
shift += 7;
|
|
}
|
|
n |= b << shift;
|
|
shift += 7;
|
|
return shift > 32 ? (n << (32 - shift)) >> (32 - shift) : n;
|
|
};
|
|
const popValue = function(formatter) {
|
|
const loc = stack.pop();
|
|
if (loc instanceof Value) {
|
|
return formatter.fromValue(loc);
|
|
}
|
|
return formatter.fromAddr(loc);
|
|
};
|
|
let i = 0,
|
|
a,
|
|
b;
|
|
const stack = [frame_base];
|
|
while (i < buf.length) {
|
|
const code = buf[i++];
|
|
switch (code) {
|
|
case 0x03 /* DW_OP_addr */:
|
|
stack.push(Uint32Formatter.fromAddr(readU32()));
|
|
break;
|
|
case 0x08 /* DW_OP_const1u 0x08 1 1-byte constant */:
|
|
stack.push(readU8());
|
|
break;
|
|
case 0x09 /* DW_OP_const1s 0x09 1 1-byte constant */:
|
|
stack.push(readS8());
|
|
break;
|
|
case 0x0a /* DW_OP_const2u 0x0a 1 2-byte constant */:
|
|
stack.push(readU16());
|
|
break;
|
|
case 0x0b /* DW_OP_const2s 0x0b 1 2-byte constant */:
|
|
stack.push(readS16());
|
|
break;
|
|
case 0x0c /* DW_OP_const2u 0x0a 1 2-byte constant */:
|
|
stack.push(readU32());
|
|
break;
|
|
case 0x0d /* DW_OP_const2s 0x0b 1 2-byte constant */:
|
|
stack.push(readS32());
|
|
break;
|
|
case 0x10 /* DW_OP_constu 0x10 1 ULEB128 constant */:
|
|
stack.push(readU());
|
|
break;
|
|
case 0x11 /* DW_OP_const2s 0x0b 1 2-byte constant */:
|
|
stack.push(readS());
|
|
break;
|
|
|
|
case 0x1c /* DW_OP_minus */:
|
|
b = stack.pop();
|
|
a = stack.pop();
|
|
stack.push(`${a} - ${b}`);
|
|
break;
|
|
|
|
case 0x22 /* DW_OP_plus */:
|
|
b = stack.pop();
|
|
a = stack.pop();
|
|
stack.push(`${a} + ${b}`);
|
|
break;
|
|
|
|
case 0x23 /* DW_OP_plus_uconst */:
|
|
b = readU();
|
|
a = stack.pop();
|
|
stack.push(`${a} + ${b}`);
|
|
break;
|
|
|
|
case 0x30 /* DW_OP_lit0 */:
|
|
case 0x31:
|
|
case 0x32:
|
|
case 0x33:
|
|
case 0x34:
|
|
case 0x35:
|
|
case 0x36:
|
|
case 0x37:
|
|
case 0x38:
|
|
case 0x39:
|
|
case 0x3a:
|
|
case 0x3b:
|
|
case 0x3c:
|
|
case 0x3d:
|
|
case 0x3e:
|
|
case 0x3f:
|
|
case 0x40:
|
|
case 0x41:
|
|
case 0x42:
|
|
case 0x43:
|
|
case 0x44:
|
|
case 0x45:
|
|
case 0x46:
|
|
case 0x47:
|
|
case 0x48:
|
|
case 0x49:
|
|
case 0x4a:
|
|
case 0x4b:
|
|
case 0x4c:
|
|
case 0x4d:
|
|
case 0x4e:
|
|
case 0x4f:
|
|
stack.push(`${code - 0x30}`);
|
|
break;
|
|
|
|
case 0x93 /* DW_OP_piece */: {
|
|
a = readU();
|
|
const formatter = createPieceFormatter(a);
|
|
stack.push(popValue(formatter));
|
|
break;
|
|
}
|
|
|
|
case 0x9f /* DW_OP_stack_value */:
|
|
stack.push(new Value(stack.pop()));
|
|
break;
|
|
|
|
case 0xf6 /* WASM ext (old, FIXME phase out) */:
|
|
case 0xed /* WASM ext */:
|
|
b = readU();
|
|
a = readS();
|
|
switch (b) {
|
|
case 0:
|
|
stack.push(`var${a}`);
|
|
break;
|
|
case 1:
|
|
stack.push(`global${a}`);
|
|
break;
|
|
default:
|
|
stack.push(`ti${b}(${a})`);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// Unknown encoding, baling out
|
|
return null;
|
|
}
|
|
}
|
|
// FIXME use real DWARF type information
|
|
return popValue(typeFormatter);
|
|
}
|
|
|
|
function decodeExpr(expr) {
|
|
if (expr.includes("//")) {
|
|
expr = expr.slice(0, expr.indexOf("//")).trim();
|
|
}
|
|
const code = new Uint8Array(expr.length >> 1);
|
|
for (let i = 0; i < code.length; i++) {
|
|
code[i] = parseInt(expr.substr(i << 1, 2), 16);
|
|
}
|
|
const typeFormatter = Int32Formatter;
|
|
return toJS(code, typeFormatter) || `dwarf("${expr}")`;
|
|
}
|
|
|
|
module.exports = {
|
|
decodeExpr,
|
|
};
|